-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Pie trace cleaning #159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Pie trace cleaning #159
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's no functions in this file, so no need for
'use strict';
That said, I don't mind making
'use strict'
for all files even the one without functions.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bpostlethwaite what's your take on ⏫ ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am inclined to put it everywhere so we don't have to think about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bpostlethwaite 🍻 thanks