Skip to content

Commit d9fab15

Browse files
committed
Cartesian dropline support
Draw droplines to the x and y axes on hover if the option is enabled and we're not on 'compare' hovermode.
1 parent 2b24f9d commit d9fab15

File tree

3 files changed

+69
-22
lines changed

3 files changed

+69
-22
lines changed

src/components/dragelement/unhover.js

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ unhover.raw = function unhoverRaw(gd, evt) {
4141
}
4242

4343
fullLayout._hoverlayer.selectAll('g').remove();
44+
fullLayout._hoverlayer.selectAll('line').remove();
4445
gd._hoverdata = undefined;
4546

4647
if(evt.target && oldhoverdata) {

src/plot_api/plot_config.js

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

51+
// display droplines on cartesian graphs
52+
showDroplines: false,
53+
5154
// enable axis pan/zoom drag handles
5255
showAxisDragHandles: true,
5356

src/plots/cartesian/graph_interact.js

+65-22
Original file line numberDiff line numberDiff line change
@@ -559,30 +559,8 @@ function hover(gd, evt, subplot) {
559559
// nothing left: remove all labels and quit
560560
if(hoverData.length === 0) return dragElement.unhoverRaw(gd, evt);
561561

562-
// if there's more than one horz bar trace,
563-
// rotate the labels so they don't overlap
564-
var rotateLabels = hovermode === 'y' && searchData.length > 1;
565-
566562
hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; });
567563

568-
var bgColor = Color.combine(
569-
fullLayout.plot_bgcolor || Color.background,
570-
fullLayout.paper_bgcolor
571-
);
572-
573-
var labelOpts = {
574-
hovermode: hovermode,
575-
rotateLabels: rotateLabels,
576-
bgColor: bgColor,
577-
container: fullLayout._hoverlayer,
578-
outerContainer: fullLayout._paperdiv
579-
};
580-
var hoverLabels = createHoverText(hoverData, labelOpts);
581-
582-
hoverAvoidOverlaps(hoverData, rotateLabels ? 'xa' : 'ya');
583-
584-
alignHoverText(hoverLabels, rotateLabels);
585-
586564
// lastly, emit custom hover/unhover events
587565
var oldhoverdata = gd._hoverdata,
588566
newhoverdata = [];
@@ -614,6 +592,38 @@ function hover(gd, evt, subplot) {
614592

615593
gd._hoverdata = newhoverdata;
616594

595+
if(gd._context.showDroplines && hoverChanged(gd, evt, oldhoverdata)) {
596+
var droplineOpts = {
597+
hovermode: hovermode,
598+
container: fullLayout._hoverlayer,
599+
outerContainer: fullLayout._paperdiv
600+
};
601+
createDroplines(hoverData, droplineOpts);
602+
}
603+
604+
// if there's more than one horz bar trace,
605+
// rotate the labels so they don't overlap
606+
var rotateLabels = hovermode === 'y' && searchData.length > 1;
607+
608+
var bgColor = Color.combine(
609+
fullLayout.plot_bgcolor || Color.background,
610+
fullLayout.paper_bgcolor
611+
);
612+
613+
var labelOpts = {
614+
hovermode: hovermode,
615+
rotateLabels: rotateLabels,
616+
bgColor: bgColor,
617+
container: fullLayout._hoverlayer,
618+
outerContainer: fullLayout._paperdiv
619+
};
620+
621+
var hoverLabels = createHoverText(hoverData, labelOpts);
622+
623+
hoverAvoidOverlaps(hoverData, rotateLabels ? 'xa' : 'ya');
624+
625+
alignHoverText(hoverLabels, rotateLabels);
626+
617627
// TODO: tagName hack is needed to appease geo.js's hack of using evt.target=true
618628
// we should improve the "fx" API so other plots can use it without these hack.
619629
if(evt.target && evt.target.tagName) {
@@ -818,8 +828,41 @@ fx.loneUnhover = function(containerOrSelection) {
818828
d3.select(containerOrSelection);
819829

820830
selection.selectAll('g.hovertext').remove();
831+
selection.selectAll('line.dropline').remove();
821832
};
822833

834+
function createDroplines(hoverData, opts) {
835+
var hovermode = opts.hovermode,
836+
container = opts.container;
837+
838+
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;
844+
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+
}
865+
823866
function createHoverText(hoverData, opts) {
824867
var hovermode = opts.hovermode,
825868
rotateLabels = opts.rotateLabels,

0 commit comments

Comments
 (0)