Skip to content

Commit 51fcb2e

Browse files
authoredNov 15, 2017
Merge pull request #2156 from cixzhang/colorway-layout
adding layout.colorway
2 parents 5388d32 + 2877e0e commit 51fcb2e

File tree

8 files changed

+132
-13
lines changed

8 files changed

+132
-13
lines changed
 

‎src/lib/coerce.js

+16
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ exports.valObjectMeta = {
141141
else propOut.set(dflt);
142142
}
143143
},
144+
colorlist: {
145+
description: [
146+
'A list of colors.',
147+
'Must be an {array} containing valid colors.',
148+
].join(' '),
149+
requiredOpts: [],
150+
otherOpts: ['dflt'],
151+
coerceFunction: function(v, propOut, dflt) {
152+
function isColor(color) {
153+
return tinycolor(color).isValid();
154+
}
155+
if(!Array.isArray(v) || !v.length) propOut.set(dflt);
156+
else if(v.every(isColor)) propOut.set(v);
157+
else propOut.set(dflt);
158+
}
159+
},
144160
colorscale: {
145161
description: [
146162
'A Plotly colorscale either picked by a name:',

‎src/plots/layout_attributes.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -175,5 +175,12 @@ module.exports = {
175175
role: 'info',
176176
editType: 'legend',
177177
description: 'Determines whether or not a legend is drawn.'
178-
}
178+
},
179+
colorway: {
180+
valType: 'colorlist',
181+
dflt: colorAttrs.defaults,
182+
role: 'style',
183+
editType: 'calc',
184+
description: 'Sets the default trace colors.'
185+
},
179186
};

‎src/plots/plots.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,9 @@ plots.supplyFrameDefaults = function(frameIn) {
950950
};
951951

952952
plots.supplyTraceDefaults = function(traceIn, traceOutIndex, layout, traceInIndex) {
953+
var colorway = layout.colorway || Color.defaults;
953954
var traceOut = {},
954-
defaultColor = Color.defaults[traceOutIndex % Color.defaults.length];
955+
defaultColor = colorway[traceOutIndex % colorway.length];
955956

956957
function coerce(attr, dflt) {
957958
return Lib.coerce(traceIn, traceOut, plots.attributes, attr, dflt);
@@ -1138,6 +1139,8 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) {
11381139
coerce('separators');
11391140
coerce('hidesources');
11401141

1142+
coerce('colorway');
1143+
11411144
Registry.getComponentMethod(
11421145
'calendars',
11431146
'handleDefaults'
@@ -2171,6 +2174,7 @@ plots.doCalcdata = function(gd, traces) {
21712174

21722175
// for sharing colors across pies (and for legend)
21732176
fullLayout._piecolormap = {};
2177+
fullLayout._piecolorway = null;
21742178
fullLayout._piedefaultcolorcount = 0;
21752179

21762180
// If traces were specified and this trace was not included,

‎src/traces/pie/calc.js

+26-11
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ module.exports = function calc(gd, trace) {
2121
var colors = trace.marker.colors;
2222
var cd = [];
2323
var fullLayout = gd._fullLayout;
24+
var colorWay = fullLayout.colorway;
2425
var colorMap = fullLayout._piecolormap;
2526
var allThisTraceLabels = {};
2627
var vTotal = 0;
2728
var hiddenLabels = fullLayout.hiddenlabels || [];
2829

2930
var i, v, label, hidden, pt;
3031

32+
if(!fullLayout._piecolorway && colorWay !== Color.defaults) {
33+
fullLayout._piecolorway = generateDefaultColors(colorWay);
34+
}
35+
3136
if(trace.dlabel) {
3237
labels = new Array(vals.length);
3338
for(i = 0; i < vals.length; i++) {
@@ -107,7 +112,10 @@ module.exports = function calc(gd, trace) {
107112
pt.color = colorMap[pt.label];
108113
}
109114
else {
110-
colorMap[pt.label] = pt.color = nextDefaultColor(fullLayout._piedefaultcolorcount);
115+
colorMap[pt.label] = pt.color = nextDefaultColor(
116+
fullLayout._piedefaultcolorcount,
117+
fullLayout._piecolorway
118+
);
111119
fullLayout._piedefaultcolorcount++;
112120
}
113121
}
@@ -148,22 +156,29 @@ module.exports = function calc(gd, trace) {
148156
*/
149157
var pieDefaultColors;
150158

151-
function nextDefaultColor(index) {
159+
function nextDefaultColor(index, pieColorWay) {
152160
if(!pieDefaultColors) {
153161
// generate this default set on demand (but then it gets saved in the module)
154162
var mainDefaults = Color.defaults;
155-
pieDefaultColors = mainDefaults.slice();
163+
pieDefaultColors = generateDefaultColors(mainDefaults);
164+
}
156165

157-
var i;
166+
var pieColors = pieColorWay || pieDefaultColors;
167+
return pieColors[index % pieColors.length];
168+
}
158169

159-
for(i = 0; i < mainDefaults.length; i++) {
160-
pieDefaultColors.push(tinycolor(mainDefaults[i]).lighten(20).toHexString());
161-
}
170+
function generateDefaultColors(colorList) {
171+
var i;
162172

163-
for(i = 0; i < Color.defaults.length; i++) {
164-
pieDefaultColors.push(tinycolor(mainDefaults[i]).darken(20).toHexString());
165-
}
173+
var pieColors = colorList.slice();
174+
175+
for(i = 0; i < colorList.length; i++) {
176+
pieColors.push(tinycolor(colorList[i]).lighten(20).toHexString());
177+
}
178+
179+
for(i = 0; i < colorList.length; i++) {
180+
pieColors.push(tinycolor(colorList[i]).darken(20).toHexString());
166181
}
167182

168-
return pieDefaultColors[index % pieDefaultColors.length];
183+
return pieColors;
169184
}
60.3 KB
Loading

‎test/image/mocks/layout-colorway.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"data": [
3+
{"y": [8, 7, 7, 6, 5, 4, 4, 3, 2, 2, 3]},
4+
{"y": [7, 7, 6, 5, 4, 4, 3, 2, 2, 3, 8]},
5+
{"y": [7, 6, 5, 4, 4, 3, 2, 2, 3, 8, 7]},
6+
{"y": [6, 5, 4, 4, 3, 2, 2, 3, 8, 7, 7]},
7+
{"y": [5, 4, 4, 3, 2, 2, 3, 8, 7, 7, 6]},
8+
{
9+
"labels": ["a","b","c","c","c","a","d","e","f","f","g","h"],
10+
"type": "pie",
11+
"domain": {"x": [0, 0.4]}
12+
}
13+
],
14+
"layout": {
15+
"title": "Custom Trace Color Defaults",
16+
"colorway": [
17+
"#DE5845",
18+
"#E83898",
19+
"#A83DD1",
20+
"#5A38E8",
21+
"#3C71DE"
22+
],
23+
"xaxis": {
24+
"domain": [0.4, 1]
25+
}
26+
}
27+
}

‎test/jasmine/tests/lib_test.js

+9
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,15 @@ describe('Test lib.js:', function() {
10731073
});
10741074
});
10751075

1076+
it('should work for valType \'colorlist\' where', function() {
1077+
var shouldPass = [['red'], ['#ffffff'], ['rgba(0,0,0,1)'], ['red', 'green', 'blue']],
1078+
shouldFail = [1, null, undefined, {}, [], 'red', ['red', null]];
1079+
1080+
assert(shouldPass, shouldFail, {
1081+
valType: 'colorlist'
1082+
});
1083+
});
1084+
10761085
it('should work for valType \'colorscale\' where', function() {
10771086
var good = [ [0, 'red'], [1, 'blue'] ],
10781087
bad = [ [0.1, 'red'], [1, 'blue'] ],

‎test/jasmine/tests/pie_test.js

+41
Original file line numberDiff line numberDiff line change
@@ -546,3 +546,44 @@ describe('Test event data of interactions on a pie plot:', function() {
546546
});
547547
});
548548
});
549+
550+
describe('pie relayout', function() {
551+
var gd;
552+
553+
beforeEach(function() { gd = createGraphDiv(); });
554+
555+
afterEach(destroyGraphDiv);
556+
557+
it('will update colors when colorway is updated', function(done) {
558+
var originalColors = [
559+
'rgb(255,0,0)',
560+
'rgb(0,255,0)',
561+
'rgb(0,0,255)',
562+
];
563+
564+
var relayoutColors = [
565+
'rgb(255,255,0)',
566+
'rgb(0,255,255)',
567+
'rgb(255,0,255)',
568+
];
569+
570+
function checkRelayoutColor(d, i) {
571+
expect(this.style.fill.replace(/\s/g, '')).toBe(relayoutColors[i]);
572+
}
573+
574+
Plotly.newPlot(gd, [{
575+
labels: ['a', 'b', 'c', 'a', 'b', 'a'],
576+
type: 'pie'
577+
}], {
578+
colorway: originalColors
579+
})
580+
.then(function() {
581+
return Plotly.relayout(gd, 'colorway', relayoutColors);
582+
})
583+
.then(function() {
584+
var slices = d3.selectAll('.slice path');
585+
slices.each(checkRelayoutColor);
586+
})
587+
.then(done);
588+
});
589+
});

0 commit comments

Comments
 (0)
Please sign in to comment.