Skip to content

Commit e79f045

Browse files
authored
Merge pull request #6216 from plotly/parcoords-unselected-line-color
add `unselected.line.color` and `unselected.line.opacity` options to `parcoords` trace
2 parents 9a2e727 + 9203fe5 commit e79f045

14 files changed

+203
-5
lines changed

draftlogs/6216_add.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Add `unselected.line.color` and `unselected.line.opacity` options to `parcoords` trace [[#6216](https://github.com/plotly/plotly.js/pull/6216)]

src/traces/parcoords/attributes.js

+29-1
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,33 @@ module.exports = {
133133
autoColorDflt: false,
134134
editTypeOverride: 'calc'
135135
})
136-
)
136+
),
137+
138+
unselected: {
139+
line: {
140+
color: {
141+
valType: 'color',
142+
dflt: '#777',
143+
editType: 'plot',
144+
description: [
145+
'Sets the base color of unselected lines.',
146+
'in connection with `unselected.line.opacity`.'
147+
].join(' ')
148+
},
149+
opacity: {
150+
valType: 'number',
151+
min: 0,
152+
max: 1,
153+
dflt: 'auto',
154+
editType: 'plot',
155+
description: [
156+
'Sets the opacity of unselected lines.',
157+
'The default *auto* decreases the opacity smoothly as the number of lines increases.',
158+
'Use *1* to achieve exact `unselected.line.color`.'
159+
].join(' ')
160+
},
161+
editType: 'plot'
162+
},
163+
editType: 'plot'
164+
}
137165
};

src/traces/parcoords/constants.js

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ module.exports = {
1111
layers: ['contextLineLayer', 'focusLineLayer', 'pickLineLayer'],
1212
axisTitleOffset: 28,
1313
axisExtentOffset: 10,
14-
deselectedLineColor: '#777',
1514
bar: {
1615
width: 4, // Visible width of the filter bar
1716
captureWidth: 10, // Mouse-sensitive width for interaction (Fitts law)

src/traces/parcoords/defaults.js

+3
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
107107

108108
coerce('labelangle');
109109
coerce('labelside');
110+
111+
coerce('unselected.line.color');
112+
coerce('unselected.line.opacity');
110113
};

src/traces/parcoords/lines.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ function makeItem(
183183
var layoutWidth = model.layoutWidth * plotGlPixelRatio;
184184

185185
var deselectedLinesColor = model.deselectedLines.color;
186+
var deselectedLinesOpacity = model.deselectedLines.opacity;
186187

187188
var itemModel = Lib.extendFlat({
188189
key: crossfilterDimensionIndex,
@@ -206,8 +207,8 @@ function makeItem(
206207
deselectedLinesColor[0] / 255,
207208
deselectedLinesColor[1] / 255,
208209
deselectedLinesColor[2] / 255,
209-
deselectedLinesColor[3] < 1 ?
210-
deselectedLinesColor[3] :
210+
deselectedLinesOpacity !== 'auto' ?
211+
deselectedLinesColor[3] * deselectedLinesOpacity :
211212
Math.max(1 / 255, Math.pow(1 / model.lines.color.length, 1 / 3))
212213
],
213214

src/traces/parcoords/parcoords.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ function model(layout, d, i) {
149149
var trace = cd0.trace;
150150
var lineColor = helpers.convertTypedArray(cd0.lineColor);
151151
var line = trace.line;
152-
var deselectedLines = {color: rgba(c.deselectedLineColor)};
152+
var deselectedLines = {
153+
color: rgba(trace.unselected.line.color),
154+
opacity: trace.unselected.line.opacity
155+
};
153156
var cOpts = Colorscale.extractOpts(line);
154157
var cscale = cOpts.reversescale ? Colorscale.flipScale(cd0.cscale) : cd0.cscale;
155158
var domain = trace.domain;
Loading
Loading
Loading

test/image/mocks/gl2d_parcoords_256_colors.json

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
"data": [
33
{
44
"type": "parcoords",
5+
"unselected": {
6+
"line": {
7+
"color": "blue"
8+
}
9+
},
510
"line": {
611
"colorscale": [
712
[

test/image/mocks/gl2d_parcoords_constraints.json

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"layout": {
3+
"paper_bgcolor": "lightgray",
34
"width": 1000,
45
"height": 400
56
},
@@ -24,6 +25,13 @@
2425
]
2526
},
2627

28+
"unselected": {
29+
"line": {
30+
"opacity": 1,
31+
"color": "white"
32+
}
33+
},
34+
2735
"dimensions": [
2836
{
2937
"label": "±1.1",

test/image/mocks/gl2d_parcoords_dark_background.json

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
"color": [-41, -1317, -164, -1856, -79, -931, -191, -2983, -341, -3846, -278, -3019, -523, -2357, -985, -3447, -211, -2842, -458, -4388, -784, -2563, -935, -2253, -313, -3667, -1479, -1030, -632, -623, -1945, -1324, -1221, -878, -947, -1615, -697, -575, -482, -905, -869, -433, -484, -349, -667, -248, -1135, -888, -1019, -223, -2067, -729, -579, -659, -334, -340, -554, -455, -377, -375, -453, -834, -934, -334, -369, -290, -354, -497, -490, -329, -729, -1794, -151, -1162, -3935, -1013, -509, -825, -997, -320, -680, -422, -785, -542, -563, -489, -1283, -680, -78, -450, -514, -449, -548, -661, -641, -503, -570, -257, -394, -450]
2121
},
2222

23+
"unselected": {
24+
"line": {
25+
"opacity": 0.5
26+
}
27+
},
28+
2329
"dimensions": [
2430
{
2531
"constraintrange": [100000, 150000],

test/jasmine/tests/parcoords_test.js

+122
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,128 @@ describe('parcoords Lifecycle methods', function() {
892892
})
893893
.then(done, done.fail);
894894
});
895+
896+
it('@gl unselected.line.color `Plotly.restyle` should change context layer line.color', function(done) {
897+
var testLayer = '.gl-canvas-context';
898+
899+
var list1 = [];
900+
var list2 = [];
901+
for(var i = 0; i <= 100; i++) {
902+
list1[i] = i;
903+
list2[i] = 100 - i;
904+
}
905+
906+
Plotly.newPlot(gd, [{
907+
type: 'parcoords',
908+
dimensions: [{
909+
constraintrange: [1, 10],
910+
values: list1
911+
}, {
912+
values: list2
913+
}],
914+
line: {color: '#0F0'},
915+
unselected: {line: {color: '#F00'}}
916+
}], {
917+
margin: {
918+
t: 0,
919+
b: 0,
920+
l: 0,
921+
r: 0
922+
},
923+
width: 300,
924+
height: 200
925+
})
926+
.then(function() {
927+
var rgb = getAvgPixelByChannel(testLayer);
928+
expect(rgb[0]).not.toBe(0, 'red');
929+
expect(rgb[1]).toBe(0, 'no green');
930+
expect(rgb[2]).toBe(0, 'no blue');
931+
932+
return Plotly.restyle(gd, 'unselected.line.color', '#00F');
933+
})
934+
.then(function() {
935+
var rgb = getAvgPixelByChannel(testLayer);
936+
expect(rgb[0]).toBe(0, 'no red');
937+
expect(rgb[1]).toBe(0, 'no green');
938+
expect(rgb[2]).not.toBe(0, 'blue');
939+
940+
return Plotly.restyle(gd, 'unselected.line.color', 'rgba(0,0,0,0)');
941+
})
942+
.then(function() {
943+
var rgb = getAvgPixelByChannel(testLayer);
944+
expect(rgb[0]).toBe(0, 'no red');
945+
expect(rgb[1]).toBe(0, 'no green');
946+
expect(rgb[2]).toBe(0, 'no blue');
947+
})
948+
.then(done, done.fail);
949+
});
950+
951+
it('@gl unselected.line.color `Plotly.react` should change line.color and unselected.line.color', function(done) {
952+
var unselectedLayer = '.gl-canvas-context';
953+
var selectedLayer = '.gl-canvas-focus';
954+
955+
var list1 = [];
956+
var list2 = [];
957+
for(var i = 0; i <= 100; i++) {
958+
list1[i] = i;
959+
list2[i] = 100 - i;
960+
}
961+
962+
var fig = {
963+
data: [{
964+
type: 'parcoords',
965+
dimensions: [{
966+
constraintrange: [1, 10],
967+
values: list1
968+
}, {
969+
values: list2
970+
}],
971+
line: {color: '#0F0'},
972+
unselected: {line: {color: '#F00'}}
973+
}],
974+
layout: {
975+
margin: {
976+
t: 0,
977+
b: 0,
978+
l: 0,
979+
r: 0
980+
},
981+
width: 300,
982+
height: 200
983+
}
984+
};
985+
986+
var rgb;
987+
988+
Plotly.newPlot(gd, fig)
989+
.then(function() {
990+
rgb = getAvgPixelByChannel(unselectedLayer);
991+
expect(rgb[0]).not.toBe(0, 'red');
992+
expect(rgb[1]).toBe(0, 'no green');
993+
expect(rgb[2]).toBe(0, 'no blue');
994+
995+
rgb = getAvgPixelByChannel(selectedLayer);
996+
expect(rgb[0]).toBe(0, 'no red');
997+
expect(rgb[1]).not.toBe(0, 'green');
998+
expect(rgb[2]).toBe(0, 'no blue');
999+
1000+
fig.data[0].line.color = '#FF0';
1001+
fig.data[0].unselected.line.color = '#00F';
1002+
return Plotly.react(gd, fig);
1003+
})
1004+
.then(function() {
1005+
rgb = getAvgPixelByChannel(selectedLayer);
1006+
expect(rgb[0]).not.toBe(0, 'red');
1007+
expect(rgb[1]).not.toBe(0, 'green');
1008+
expect(rgb[2]).toBe(0, 'no blue');
1009+
1010+
rgb = getAvgPixelByChannel(unselectedLayer);
1011+
expect(rgb[0]).toBe(0, 'no red');
1012+
expect(rgb[1]).toBe(0, 'no green');
1013+
expect(rgb[2]).not.toBe(0, 'blue');
1014+
})
1015+
.then(done, done.fail);
1016+
});
8951017
});
8961018

8971019
describe('parcoords hover', function() {

test/plot-schema.json

+22
Original file line numberDiff line numberDiff line change
@@ -40355,6 +40355,28 @@
4035540355
"editType": "none",
4035640356
"valType": "any"
4035740357
},
40358+
"unselected": {
40359+
"editType": "plot",
40360+
"line": {
40361+
"color": {
40362+
"description": "Sets the base color of unselected lines. in connection with `unselected.line.opacity`.",
40363+
"dflt": "#777",
40364+
"editType": "plot",
40365+
"valType": "color"
40366+
},
40367+
"editType": "plot",
40368+
"opacity": {
40369+
"description": "Sets the opacity of unselected lines. The default *auto* decreases the opacity smoothly as the number of lines increases. Use *1* to achieve exact `unselected.line.color`.",
40370+
"dflt": "auto",
40371+
"editType": "plot",
40372+
"max": 1,
40373+
"min": 0,
40374+
"valType": "number"
40375+
},
40376+
"role": "object"
40377+
},
40378+
"role": "object"
40379+
},
4035840380
"visible": {
4035940381
"description": "Determines whether or not this trace is visible. If *legendonly*, the trace is not drawn, but can appear as a legend item (provided that the legend itself is visible).",
4036040382
"dflt": true,

0 commit comments

Comments
 (0)