-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #159 from plotly/pie-trace-cleaning
Pie trace cleaning
- Loading branch information
Showing
10 changed files
with
1,032 additions
and
932 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/** | ||
* Copyright 2012-2016, Plotly, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var isNumeric = require('fast-isnumeric'); | ||
var tinycolor = require('tinycolor2'); | ||
|
||
var Color = require('../../components/color'); | ||
var helpers = require('./helpers'); | ||
|
||
module.exports = function calc(gd, trace) { | ||
var vals = trace.values, | ||
labels = trace.labels, | ||
cd = [], | ||
fullLayout = gd._fullLayout, | ||
colorMap = fullLayout._piecolormap, | ||
allThisTraceLabels = {}, | ||
needDefaults = false, | ||
vTotal = 0, | ||
hiddenLabels = fullLayout.hiddenlabels || [], | ||
i, | ||
v, | ||
label, | ||
color, | ||
hidden, | ||
pt; | ||
|
||
if(trace.dlabel) { | ||
labels = new Array(vals.length); | ||
for(i = 0; i < vals.length; i++) { | ||
labels[i] = String(trace.label0 + i * trace.dlabel); | ||
} | ||
} | ||
|
||
for(i = 0; i < vals.length; i++) { | ||
v = vals[i]; | ||
if(!isNumeric(v)) continue; | ||
v = +v; | ||
if(v < 0) continue; | ||
|
||
label = labels[i]; | ||
if(label === undefined || label === '') label = i; | ||
label = String(label); | ||
// only take the first occurrence of any given label. | ||
// TODO: perhaps (optionally?) sum values for a repeated label? | ||
if(allThisTraceLabels[label] === undefined) allThisTraceLabels[label] = true; | ||
else continue; | ||
|
||
color = tinycolor(trace.marker.colors[i]); | ||
if(color.isValid()) { | ||
color = Color.addOpacity(color, color.getAlpha()); | ||
if(!colorMap[label]) { | ||
colorMap[label] = color; | ||
} | ||
} | ||
// have we seen this label and assigned a color to it in a previous trace? | ||
else if(colorMap[label]) color = colorMap[label]; | ||
// color needs a default - mark it false, come back after sorting | ||
else { | ||
color = false; | ||
needDefaults = true; | ||
} | ||
|
||
hidden = hiddenLabels.indexOf(label) !== -1; | ||
|
||
if(!hidden) vTotal += v; | ||
|
||
cd.push({ | ||
v: v, | ||
label: label, | ||
color: color, | ||
i: i, | ||
hidden: hidden | ||
}); | ||
} | ||
|
||
if(trace.sort) cd.sort(function(a, b) { return b.v - a.v; }); | ||
|
||
/** | ||
* now go back and fill in colors we're still missing | ||
* this is done after sorting, so we pick defaults | ||
* in the order slices will be displayed | ||
*/ | ||
|
||
if(needDefaults) { | ||
for(i = 0; i < cd.length; i++) { | ||
pt = cd[i]; | ||
if(pt.color === false) { | ||
colorMap[pt.label] = pt.color = nextDefaultColor(fullLayout._piedefaultcolorcount); | ||
fullLayout._piedefaultcolorcount++; | ||
} | ||
} | ||
} | ||
|
||
// include the sum of all values in the first point | ||
if(cd[0]) cd[0].vTotal = vTotal; | ||
|
||
// now insert text | ||
if(trace.textinfo && trace.textinfo !== 'none') { | ||
var hasLabel = trace.textinfo.indexOf('label') !== -1, | ||
hasText = trace.textinfo.indexOf('text') !== -1, | ||
hasValue = trace.textinfo.indexOf('value') !== -1, | ||
hasPercent = trace.textinfo.indexOf('percent') !== -1, | ||
thisText; | ||
|
||
for(i = 0; i < cd.length; i++) { | ||
pt = cd[i]; | ||
thisText = hasLabel ? [pt.label] : []; | ||
if(hasText && trace.text[pt.i]) thisText.push(trace.text[pt.i]); | ||
if(hasValue) thisText.push(helpers.formatPieValue(pt.v)); | ||
if(hasPercent) thisText.push(helpers.formatPiePercent(pt.v / vTotal)); | ||
pt.text = thisText.join('<br>'); | ||
} | ||
} | ||
|
||
return cd; | ||
}; | ||
|
||
/** | ||
* pick a default color from the main default set, augmented by | ||
* itself lighter then darker before repeating | ||
*/ | ||
var pieDefaultColors; | ||
|
||
function nextDefaultColor(index) { | ||
if(!pieDefaultColors) { | ||
// generate this default set on demand (but then it gets saved in the module) | ||
var mainDefaults = Color.defaults; | ||
pieDefaultColors = mainDefaults.slice(); | ||
for(var i = 0; i < mainDefaults.length; i++) { | ||
pieDefaultColors.push(tinycolor(mainDefaults[i]).lighten(20).toHexString()); | ||
} | ||
for(i = 0; i < Color.defaults.length; i++) { | ||
pieDefaultColors.push(tinycolor(mainDefaults[i]).darken(20).toHexString()); | ||
} | ||
} | ||
|
||
return pieDefaultColors[index % pieDefaultColors.length]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/** | ||
* Copyright 2012-2016, Plotly, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var Lib = require('../../lib'); | ||
var attributes = require('./attributes'); | ||
|
||
module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { | ||
function coerce(attr, dflt) { | ||
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); | ||
} | ||
|
||
var coerceFont = Lib.coerceFont; | ||
|
||
var vals = coerce('values'); | ||
if(!Array.isArray(vals) || !vals.length) { | ||
traceOut.visible = false; | ||
return; | ||
} | ||
|
||
var labels = coerce('labels'); | ||
if(!Array.isArray(labels)) { | ||
coerce('label0'); | ||
coerce('dlabel'); | ||
} | ||
|
||
var lineWidth = coerce('marker.line.width'); | ||
if(lineWidth) coerce('marker.line.color'); | ||
|
||
var colors = coerce('marker.colors'); | ||
if(!Array.isArray(colors)) traceOut.marker.colors = []; // later this will get padded with default colors | ||
|
||
coerce('scalegroup'); | ||
// TODO: tilt, depth, and hole all need to be coerced to the same values within a scaleegroup | ||
// (ideally actually, depth would get set the same *after* scaling, ie the same absolute depth) | ||
// and if colors aren't specified we should match these up - potentially even if separate pies | ||
// are NOT in the same sharegroup | ||
|
||
|
||
var textData = coerce('text'); | ||
var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); | ||
|
||
coerce('hoverinfo', (layout._dataLength === 1) ? 'label+text+value+percent' : undefined); | ||
|
||
if(textInfo && textInfo !== 'none') { | ||
var textPosition = coerce('textposition'), | ||
hasBoth = Array.isArray(textPosition) || textPosition === 'auto', | ||
hasInside = hasBoth || textPosition === 'inside', | ||
hasOutside = hasBoth || textPosition === 'outside'; | ||
|
||
if(hasInside || hasOutside) { | ||
var dfltFont = coerceFont(coerce, 'textfont', layout.font); | ||
if(hasInside) coerceFont(coerce, 'insidetextfont', dfltFont); | ||
if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont); | ||
} | ||
} | ||
|
||
coerce('domain.x'); | ||
coerce('domain.y'); | ||
|
||
// 3D attributes commented out until I finish them in a later PR | ||
// var tilt = coerce('tilt'); | ||
// if(tilt) { | ||
// coerce('tiltaxis'); | ||
// coerce('depth'); | ||
// coerce('shading'); | ||
// } | ||
|
||
coerce('hole'); | ||
|
||
coerce('sort'); | ||
coerce('direction'); | ||
coerce('rotation'); | ||
|
||
coerce('pull'); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Copyright 2012-2016, Plotly, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
exports.formatPiePercent = function formatPiePercent(v) { | ||
var vRounded = (v * 100).toPrecision(3); | ||
if(vRounded.indexOf('.') !== -1) return vRounded.replace(/[.]?0+$/,'') + '%'; | ||
return vRounded + '%'; | ||
}; | ||
|
||
exports.formatPieValue = function formatPieValue(v) { | ||
var vRounded = v.toPrecision(10); | ||
if(vRounded.indexOf('.') !== -1) return vRounded.replace(/[.]?0+$/,''); | ||
return vRounded; | ||
}; |
Oops, something went wrong.