Skip to content

Commit 074e61c

Browse files
committed
clarify showspikes and improve spike color contrast
1 parent 3f9596a commit 074e61c

6 files changed

Lines changed: 64 additions & 16 deletions

File tree

‎src/plots/ternary/layout_attributes.js‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ var ternaryAxesAttrs = {
6363
].join(' ')
6464
},
6565
// spikelines
66-
showspikes: axesAttrs.showspikes,
66+
showspikes: extendFlat({}, axesAttrs.showspikes, {
67+
description: [
68+
'Determines whether or not spikes (aka droplines) are drawn for this axis.',
69+
'Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.',
70+
].join(' ')
71+
}),
6772
spikecolor: axesAttrs.spikecolor,
6873
spikethickness: axesAttrs.spikethickness,
6974
spikedash: axesAttrs.spikedash,

‎src/plots/ternary/layout_defaults.js‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ function handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut
6565
return Lib.coerce(containerIn, containerOut, axAttrs, attr, dflt);
6666
}
6767

68+
function coerce2(attr, dflt) {
69+
return Lib.coerce2(containerIn, containerOut, axAttrs, attr, dflt);
70+
}
71+
6872
coerce('uirevision', ternaryLayoutOut.uirevision);
6973

7074
containerOut.type = 'linear'; // no other types allowed for ternary
@@ -123,11 +127,18 @@ function handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut
123127
coerce('hoverformat');
124128
coerce('layer');
125129

126-
if(coerce('showspikes')) {
127-
coerce('spikecolor');
128-
coerce('spikethickness');
129-
coerce('spikedash');
130-
coerce('spikemode');
131-
coerce('spikesnap');
130+
var spikecolor = coerce2('spikecolor');
131+
var spikethickness = coerce2('spikethickness');
132+
var spikedash = coerce2('spikedash');
133+
var spikemode = coerce2('spikemode');
134+
var spikesnap = coerce2('spikesnap');
135+
var showSpikes = coerce('showspikes', !!spikecolor || !!spikethickness || !!spikedash || !!spikemode || !!spikesnap);
136+
137+
if(!showSpikes) {
138+
delete containerOut.spikecolor;
139+
delete containerOut.spikethickness;
140+
delete containerOut.spikedash;
141+
delete containerOut.spikemode;
142+
delete containerOut.spikesnap;
132143
}
133144
}

‎src/plots/ternary/ternary.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ proto.drawSpikelines = function (hoverPoint, spikePoint, cursorXVal, cursorYVal)
179179

180180
const span = this.sum - axes[0].min - axes[1].min - axes[2].min;
181181

182+
const contrastColor = Color.combine(fullLayout[this.id].bgcolor, fullLayout.paper_bgcolor);
183+
182184
let layer;
183185

184186
for(let i = 0; i < axes.length; i++) {
@@ -235,7 +237,11 @@ proto.drawSpikelines = function (hoverPoint, spikePoint, cursorXVal, cursorYVal)
235237
[this.w * (1 + fc) / 2, this.h * fc, this.w * fc, this.h] // caxis
236238
][i];
237239

238-
const color = axis.spikecolor || selectedPoint.color || axis.color;
240+
const pointColor = selectedPoint.color || axis.color;
241+
const dfltColor = Color.wcagContrast(pointColor, contrastColor) < 1.5
242+
? Color.contrast(contrastColor)
243+
: pointColor;
244+
const color = axis.spikecolor || dfltColor;
239245
const thickness = axis.spikethickness;
240246
const mode = axis.spikemode;
241247

‎src/types/generated/schema.d.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14752,7 +14752,7 @@ export interface TernaryLayout {
1475214752
*/
1475314753
showline?: boolean;
1475414754
/**
14755-
* Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.
14755+
* Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.
1475614756
* @default false
1475714757
*/
1475814758
showspikes?: boolean;
@@ -14941,7 +14941,7 @@ export interface TernaryLayout {
1494114941
*/
1494214942
showline?: boolean;
1494314943
/**
14944-
* Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.
14944+
* Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.
1494514945
* @default false
1494614946
*/
1494714947
showspikes?: boolean;
@@ -15135,7 +15135,7 @@ export interface TernaryLayout {
1513515135
*/
1513615136
showline?: boolean;
1513715137
/**
15138-
* Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.
15138+
* Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.
1513915139
* @default false
1514015140
*/
1514115141
showspikes?: boolean;

‎test/jasmine/tests/ternary_test.js‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,30 @@ describe('ternary spikelines', function() {
787787
.then(done, done.fail);
788788
});
789789

790+
it('uses a contrasting default spike color against background', function(done) {
791+
var trace = Lib.extendDeep({}, data[0], {
792+
marker: {color: 'white'}
793+
});
794+
var options = {
795+
ternary: {
796+
sum: 100,
797+
bgcolor: '#eee', // light gray
798+
aaxis: {showspikes: true}
799+
}
800+
};
801+
802+
Plotly.newPlot(gd, [trace], options).then(function() {
803+
hoverAt(-35, 49);
804+
805+
var line = gd.querySelector('.ternary-spikes line');
806+
var labelBox = gd.querySelector('.ternary-spikelabel path');
807+
808+
expect(line.style.stroke).toBe(rgb('#444'));
809+
expect(labelBox.style.fill).toBe(rgb('#444'));
810+
})
811+
.then(done, done.fail);
812+
});
813+
790814
it('keeps redrawn spikes behind the hover label', function(done) {
791815
Plotly.newPlot(gd, data, layout).then(function() {
792816
hoverAt(-35, 49);
@@ -1002,9 +1026,9 @@ describe('ternary defaults', function() {
10021026
it('defaults spikes off and coerces each enabled axis independently', function() {
10031027
layoutIn = {ternary: {
10041028
aaxis: {showspikes: true},
1005-
baxis: {showspikes: true, spikecolor: 'red', spikethickness: 2,
1029+
baxis: {spikecolor: 'red', spikethickness: 2,
10061030
spikedash: 'dot', spikemode: 'across+marker', spikesnap: 'cursor'},
1007-
caxis: {spikecolor: 'blue'}
1031+
caxis: {showspikes: false, spikecolor: 'blue'}
10081032
}};
10091033
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
10101034
var ternary = layoutOut.ternary;
@@ -1013,13 +1037,15 @@ describe('ternary defaults', function() {
10131037
expect(ternary.aaxis.spikemode).toBe('toaxis');
10141038
expect(ternary.aaxis.spikethickness).toBe(3);
10151039
expect(ternary.aaxis.spikedash).toBe('dash');
1040+
expect(ternary.baxis.showspikes).toBe(true);
10161041
expect(ternary.baxis.spikecolor).toBe('red');
10171042
expect(ternary.baxis.spikethickness).toBe(2);
10181043
expect(ternary.baxis.spikedash).toBe('dot');
10191044
expect(ternary.baxis.spikemode).toBe('across+marker');
10201045
expect(ternary.baxis.spikesnap).toBe('cursor');
10211046
expect(ternary.caxis.showspikes).toBe(false);
10221047
expect(ternary.caxis.spikecolor).toBeUndefined();
1048+
expect(ternary.caxis.spikethickness).toBeUndefined();
10231049
});
10241050

10251051
it('should coerce \'min\' values to 0 and delete them for user data if they contradict', function() {

‎test/plot-schema.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10786,7 +10786,7 @@
1078610786
"valType": "boolean"
1078710787
},
1078810788
"showspikes": {
10789-
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.",
10789+
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.",
1079010790
"dflt": false,
1079110791
"editType": "plot",
1079210792
"valType": "boolean"
@@ -11344,7 +11344,7 @@
1134411344
"valType": "boolean"
1134511345
},
1134611346
"showspikes": {
11347-
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.",
11347+
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.",
1134811348
"dflt": false,
1134911349
"editType": "plot",
1135011350
"valType": "boolean"
@@ -11908,7 +11908,7 @@
1190811908
"valType": "boolean"
1190911909
},
1191011910
"showspikes": {
11911-
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Note that spikes will never be drawn when `hovermode` is *false*.",
11911+
"description": "Determines whether or not spikes (aka droplines) are drawn for this axis. Ternary spikes are accompanied by axis value labels formatted according to `hoverformat`.",
1191211912
"dflt": false,
1191311913
"editType": "plot",
1191411914
"valType": "boolean"

0 commit comments

Comments
 (0)