Skip to content

Commit 5d39b53

Browse files
committed
Removed chart config for showDroplines
Added axis layout option for showspikes Added background behind droplines Added axis indicator marker, including on free anchored axes Always draw dropline to chart limit, including for shared axes - not drawing all the way to free anchored axes
1 parent d9fab15 commit 5d39b53

File tree

5 files changed

+103
-30
lines changed

5 files changed

+103
-30
lines changed

src/components/dragelement/unhover.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ unhover.raw = function unhoverRaw(gd, evt) {
4242

4343
fullLayout._hoverlayer.selectAll('g').remove();
4444
fullLayout._hoverlayer.selectAll('line').remove();
45+
fullLayout._hoverlayer.selectAll('circle').remove();
4546
gd._hoverdata = undefined;
4647

4748
if(evt.target && oldhoverdata) {

src/plot_api/plot_config.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ module.exports = {
4848
// new users see some hints about interactivity
4949
showTips: true,
5050

51-
// display droplines on cartesian graphs
52-
showDroplines: false,
53-
5451
// enable axis pan/zoom drag handles
5552
showAxisDragHandles: true,
5653

src/plots/cartesian/axis_defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
9999
coerce('range');
100100
containerOut.cleanRange();
101101

102+
coerce('showspikes');
103+
102104
handleTickValueDefaults(containerIn, containerOut, coerce, axType);
103105
handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options);
104106
handleTickMarkDefaults(containerIn, containerOut, coerce, options);

src/plots/cartesian/graph_interact.js

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ function hover(gd, evt, subplot) {
592592

593593
gd._hoverdata = newhoverdata;
594594

595-
if(gd._context.showDroplines && hoverChanged(gd, evt, oldhoverdata)) {
595+
if(hoverChanged(gd, evt, oldhoverdata)) {
596596
var droplineOpts = {
597597
hovermode: hovermode,
598598
container: fullLayout._hoverlayer,
@@ -829,38 +829,102 @@ fx.loneUnhover = function(containerOrSelection) {
829829

830830
selection.selectAll('g.hovertext').remove();
831831
selection.selectAll('line.dropline').remove();
832+
selection.selectAll('circle.dropline').remove();
832833
};
833834

834835
function createDroplines(hoverData, opts) {
835836
var hovermode = opts.hovermode,
836-
container = opts.container;
837-
837+
container = opts.container,
838+
outerContainer = opts.outerContainer;
838839
if(hovermode !== 'closest') return;
839-
var c0 = hoverData[0];
840-
var x = (c0.x0 + c0.x1) / 2;
841-
var y = (c0.y0 + c0.y1) / 2;
842-
var xOffset = c0.xa._offset;
843-
var yOffset = c0.ya._offset;
840+
var c0 = hoverData[0],
841+
x = (c0.x0 + c0.x1) / 2,
842+
y = (c0.y0 + c0.y1) / 2,
843+
xOffset = c0.xa._offset,
844+
yOffset = c0.ya._offset,
845+
xPoint = xOffset + x,
846+
yPoint = yOffset + y,
847+
xSide = c0.xa.side,
848+
ySide = c0.ya.side,
849+
xLength = c0.xa._length,
850+
yLength = c0.ya._length,
851+
xEdge = c0.ya._boundingBox.left + (ySide === 'left' ? c0.ya._boundingBox.width : 0),
852+
yEdge = c0.xa._boundingBox.top + (xSide === 'top' ? c0.xa._boundingBox.height : 0),
853+
outerBBox = outerContainer.node().getBoundingClientRect(),
854+
xFreeBase = xOffset + (ySide === 'right' ? xLength : 0),
855+
yFreeBase = yOffset + (xSide === 'top' ? yLength : 0),
856+
xAnchoredBase = xEdge - outerBBox.left,
857+
yAnchoredBase = yEdge - outerBBox.top,
858+
xBase = c0.ya.anchor === 'free' ? xFreeBase : xAnchoredBase,
859+
yBase = c0.xa.anchor === 'free' ? yFreeBase : yAnchoredBase,
860+
color = c0.color;
861+
862+
// Remove old dropline items
844863
container.selectAll('line.dropline').remove();
845-
container.append('line')
846-
.attr('x1', xOffset + (c0.ya.side === 'right' ? c0.xa._length : 0))
847-
.attr('x2', xOffset + x)
848-
.attr('y1', yOffset + y)
849-
.attr('y2', yOffset + y)
850-
.attr('stroke-width', 3)
851-
.attr('stroke', c0.color)
852-
.attr('stroke-dasharray', '5,5')
853-
.attr('class', 'dropline');
854-
855-
container.append('line')
856-
.attr('x1', xOffset + x)
857-
.attr('x2', xOffset + x)
858-
.attr('y1', yOffset + y)
859-
.attr('y2', yOffset + c0.ya._length)
860-
.attr('stroke-width', 3)
861-
.attr('stroke', c0.color)
862-
.attr('stroke-dasharray', '5,5')
863-
.attr('class', 'dropline');
864+
container.selectAll('circle.dropline').remove();
865+
866+
867+
if(c0.ya.showspikes) {
868+
// Background horizontal Line (to y-axis)
869+
container.append('line')
870+
.attr('x1', xBase)
871+
.attr('x2', xPoint)
872+
.attr('y1', yPoint)
873+
.attr('y2', yPoint)
874+
.attr('stroke-width', 5)
875+
.attr('stroke', '#fff')
876+
.attr('class', 'dropline');
877+
878+
// Foreground horizontal line (to y-axis)
879+
container.append('line')
880+
.attr('x1', xBase)
881+
.attr('x2', xPoint)
882+
.attr('y1', yPoint)
883+
.attr('y2', yPoint)
884+
.attr('stroke-width', 3)
885+
.attr('stroke', color)
886+
.attr('stroke-dasharray', '5,5')
887+
.attr('class', 'dropline');
888+
889+
// Y axis marker
890+
container.append('circle')
891+
.attr('cx', xBase)
892+
.attr('cy', yPoint)
893+
.attr('r', 3)
894+
.attr('fill', color)
895+
.attr('class', 'dropline');
896+
}
897+
898+
if(c0.xa.showspikes) {
899+
// Background vertical line (to x-axis)
900+
container.append('line')
901+
.attr('x1', xPoint)
902+
.attr('x2', xPoint)
903+
.attr('y1', yPoint)
904+
.attr('y2', yBase)
905+
.attr('stroke-width', 5)
906+
.attr('stroke', '#fff')
907+
.attr('class', 'dropline');
908+
909+
// Foreground vertical line (to x-axis)
910+
container.append('line')
911+
.attr('x1', xPoint)
912+
.attr('x2', xPoint)
913+
.attr('y1', yPoint)
914+
.attr('y2', yBase)
915+
.attr('stroke-width', 3)
916+
.attr('stroke', color)
917+
.attr('stroke-dasharray', '5,5')
918+
.attr('class', 'dropline');
919+
920+
// X axis marker
921+
container.append('circle')
922+
.attr('cx', xPoint)
923+
.attr('cy', yBase)
924+
.attr('r', 3)
925+
.attr('fill', color)
926+
.attr('class', 'dropline');
927+
}
864928
}
865929

866930
function createHoverText(hoverData, opts) {

src/plots/cartesian/layout_attributes.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,15 @@ module.exports = {
244244
role: 'style',
245245
description: 'Determines whether or not the tick labels are drawn.'
246246
},
247+
showspikes: {
248+
valType: 'boolean',
249+
dflt: false,
250+
role: 'style',
251+
description: [
252+
'Determines whether or not spikes (aka droplines) are drawn for this axis.',
253+
'Note: This only takes affect when hovermode = closest'
254+
].join(' ')
255+
},
247256
tickfont: extendFlat({}, fontAttrs, {
248257
description: 'Sets the tick font.'
249258
}),

0 commit comments

Comments
 (0)