Skip to content

Commit 17d815c

Browse files
committed
Add cartesian spikeline modebar support
1 parent be47533 commit 17d815c

File tree

7 files changed

+89
-10
lines changed

7 files changed

+89
-10
lines changed

src/components/modebar/buttons.js

+48-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ function handleCartesian(gd, ev) {
183183
var mag = (val === 'in') ? 0.5 : 2,
184184
r0 = (1 + mag) / 2,
185185
r1 = (1 - mag) / 2,
186-
axList = Axes.list(gd, null, true);
186+
axList = Axes.list(gd, null, true),
187+
allEnabled = 'on';
187188

188189
var ax, axName;
189190

@@ -202,6 +203,12 @@ function handleCartesian(gd, ev) {
202203
aobj[axName + '.range[0]'] = rangeInitial[0];
203204
aobj[axName + '.range[1]'] = rangeInitial[1];
204205
}
206+
if(ax._showSpikeInitial !== undefined) {
207+
aobj[axName + '.showspike'] = ax._showSpikeInitial;
208+
if(allEnabled === 'on' && !ax._showSpikeInitial) {
209+
allEnabled = 'off';
210+
}
211+
}
205212
}
206213
else {
207214
var rangeNow = [
@@ -219,12 +226,17 @@ function handleCartesian(gd, ev) {
219226
}
220227
}
221228
}
229+
fullLayout._cartesianSpikesEnabled = allEnabled;
222230
}
223231
else {
224232
// if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y'
225233
if(astr === 'hovermode' && (val === 'x' || val === 'y')) {
226234
val = fullLayout._isHoriz ? 'y' : 'x';
227235
button.setAttribute('data-val', val);
236+
if(val !== 'closest') {
237+
fullLayout._cartesianSpikesEnabled = 'off';
238+
aobj = setSpikelineVisibility(gd);
239+
}
228240
}
229241

230242
aobj[astr] = val;
@@ -518,3 +530,38 @@ modeBarButtons.resetViews = {
518530
// geo subplots.
519531
}
520532
};
533+
534+
modeBarButtons.toggleSpikelines = {
535+
name: 'toggleSpikelines',
536+
title: 'Toggle Spike Lines',
537+
icon: Icons.home,
538+
attr: '_cartesianSpikesEnabled',
539+
val: 'on',
540+
click: function(gd) {
541+
var fullLayout = gd._fullLayout;
542+
543+
fullLayout._cartesianSpikesEnabled = fullLayout.hovermode === 'closest' ?
544+
(fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on') : 'on';
545+
546+
var aobj = setSpikelineVisibility(gd);
547+
548+
aobj.hovermode = 'closest';
549+
Plotly.relayout(gd, aobj);
550+
}
551+
};
552+
553+
function setSpikelineVisibility(gd) {
554+
var fullLayout = gd._fullLayout,
555+
axList = Axes.list(gd, null, true),
556+
ax,
557+
axName,
558+
aobj = {};
559+
560+
for(var i = 0; i < axList.length; i++) {
561+
ax = axList[i];
562+
axName = ax._name;
563+
aobj[axName + '.showspike'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : false;
564+
}
565+
566+
return aobj;
567+
}

src/components/modebar/manage.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {
138138
addGroup(['hoverClosestGl2d']);
139139
}
140140
else if(hasCartesian) {
141-
addGroup(['hoverClosestCartesian', 'hoverCompareCartesian']);
141+
addGroup(['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian']);
142142
}
143143
else if(hasPie) {
144144
addGroup(['hoverClosestPie']);

src/plot_api/plot_api.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,12 @@ Plotly.plot = function(gd, data, layout, config) {
151151
makePlotFramework(gd);
152152
}
153153

154-
// save initial axis range once per graph
155-
if(graphWasEmpty) Plotly.Axes.saveRangeInitial(gd);
156-
154+
if(graphWasEmpty) {
155+
// save initial axis range once per graph
156+
Plotly.Axes.saveRangeInitial(gd);
157+
// save initial show spikes once per graph
158+
Plotly.Axes.saveShowSpikeInitial(gd);
159+
}
157160

158161
// prepare the data and find the autorange
159162

src/plots/cartesian/axes.js

+29
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,35 @@ axes.saveRangeInitial = function(gd, overwrite) {
361361
return hasOneAxisChanged;
362362
};
363363

364+
// save a copy of the initial spike visibility
365+
axes.saveShowSpikeInitial = function(gd, overwrite) {
366+
var axList = axes.list(gd, '', true),
367+
hasOneAxisChanged = false,
368+
allEnabled = 'on';
369+
370+
for(var i = 0; i < axList.length; i++) {
371+
var ax = axList[i];
372+
373+
var isNew = (ax._showSpikeInitial === undefined);
374+
var hasChanged = (
375+
isNew || !(
376+
ax.showspike === ax._showspike
377+
)
378+
);
379+
380+
if((isNew) || (overwrite && hasChanged)) {
381+
ax._showSpikeInitial = ax.showspike;
382+
hasOneAxisChanged = true;
383+
}
384+
385+
if(allEnabled === 'on' && !ax.showspike) {
386+
allEnabled = 'off';
387+
}
388+
}
389+
gd._fullLayout._cartesianSpikesEnabled = allEnabled;
390+
return hasOneAxisChanged;
391+
};
392+
364393
// axes.expand: if autoranging, include new data in the outer limits
365394
// for this axis
366395
// data is an array of numbers (ie already run through ax.d2c)

src/plots/cartesian/axis_defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
9999
coerce('range');
100100
containerOut.cleanRange();
101101

102-
coerce('showspikes');
102+
coerce('showspike');
103103
coerce('spikecolor');
104104
coerce('spikethickness');
105105
coerce('spikedash');

src/plots/cartesian/graph_interact.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ function createDroplines(hoverData, opts) {
879879
container.selectAll('circle.dropline').remove();
880880

881881

882-
if(c0.ya.showspikes) {
882+
if(c0.ya.showspike) {
883883
if(ySpikeLine) {
884884
// Background horizontal Line (to y-axis)
885885
container.append('line')
@@ -913,7 +913,7 @@ function createDroplines(hoverData, opts) {
913913
}
914914
}
915915

916-
if(c0.xa.showspikes) {
916+
if(c0.xa.showspike) {
917917
if(xSpikeLine) {
918918
// Background vertical line (to x-axis)
919919
container.append('line')

src/plots/cartesian/layout_attributes.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ module.exports = {
244244
role: 'style',
245245
description: 'Determines whether or not the tick labels are drawn.'
246246
},
247-
showspikes: {
247+
showspike: {
248248
valType: 'boolean',
249-
dflt: true,
249+
dflt: false,
250250
role: 'style',
251251
description: [
252252
'Determines whether or not spikes (aka droplines) are drawn for this axis.',

0 commit comments

Comments
 (0)