Skip to content

Commit e5cee9e

Browse files
author
Daniel Gröger
committed
Use actual axis label background path instead of bounding box for collision detection
1 parent 9e75c94 commit e5cee9e

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

src/components/fx/hover.js

+39-29
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
833833
var hoverLabels = hoverText.hoverLabels;
834834

835835
if(!helpers.isUnifiedHover(hovermode)) {
836-
hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, hoverText.commonLabel);
836+
hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, hoverText.commonLabelBoundingBox);
837837
alignHoverText(hoverLabels, rotateLabels, fullLayout._invScaleX, fullLayout._invScaleY);
838838
} // TODO: tagName hack is needed to appease geo.js's hack of using eventTarget=true
839839
// we should improve the "fx" API so other plots can use it without these hack.
@@ -944,7 +944,13 @@ function createHoverText(hoverData, opts) {
944944
.classed('axistext', true);
945945
commonLabel.exit().remove();
946946

947-
var commonLabelLx, commonLabelLy;
947+
// set rect (without arrow) behind label below for later collision detection
948+
var commonLabelRect = {
949+
minX: 0,
950+
maxX: 0,
951+
minY: 0,
952+
maxY: 0
953+
};
948954
commonLabel.each(function() {
949955
var label = d3.select(this);
950956
var lpath = Lib.ensureSingle(label, 'path', '', function(s) {
@@ -998,7 +1004,7 @@ function createHoverText(hoverData, opts) {
9981004

9991005
lpath.attr('d', 'M-' + (halfWidth - HOVERARROWSIZE) + ',0' +
10001006
'L-' + (halfWidth - HOVERARROWSIZE * 2) + ',' + topsign + HOVERARROWSIZE +
1001-
'H' + (HOVERTEXTPAD + tbb.width / 2) +
1007+
'H' + (halfWidth) +
10021008
'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
10031009
'H-' + halfWidth +
10041010
'V' + topsign + HOVERARROWSIZE +
@@ -1015,12 +1021,23 @@ function createHoverText(hoverData, opts) {
10151021
} else {
10161022
lpath.attr('d', 'M0,0' +
10171023
'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE +
1018-
'H' + (HOVERTEXTPAD + tbb.width / 2) +
1024+
'H' + (halfWidth) +
10191025
'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
1020-
'H-' + (HOVERTEXTPAD + tbb.width / 2) +
1026+
'H-' + (halfWidth) +
10211027
'V' + topsign + HOVERARROWSIZE +
10221028
'H-' + HOVERARROWSIZE + 'Z');
10231029
}
1030+
1031+
commonLabelRect.minX = lx - halfWidth;
1032+
commonLabelRect.maxX = lx + halfWidth;
1033+
if(xa.side === 'top') {
1034+
// label on negative y side
1035+
commonLabelRect.minY = ly - (HOVERTEXTPAD * 2 + tbb.height);
1036+
commonLabelRect.maxY = ly - HOVERTEXTPAD;
1037+
} else {
1038+
commonLabelRect.minY = ly + HOVERTEXTPAD;
1039+
commonLabelRect.maxY = ly + (HOVERTEXTPAD * 2 + tbb.height);
1040+
}
10241041
} else {
10251042
var anchor;
10261043
var sgn;
@@ -1048,6 +1065,17 @@ function createHoverText(hoverData, opts) {
10481065
'V-' + (HOVERTEXTPAD + tbb.height / 2) +
10491066
'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z');
10501067

1068+
commonLabelRect.minY = ly - (HOVERTEXTPAD + tbb.height / 2);
1069+
commonLabelRect.maxY = ly + (HOVERTEXTPAD + tbb.height / 2);
1070+
if(ya.side === 'right') {
1071+
commonLabelRect.minX = lx + HOVERARROWSIZE;
1072+
commonLabelRect.maxX = lx + HOVERARROWSIZE + (HOVERTEXTPAD * 2 + tbb.width);
1073+
} else {
1074+
// label on negative x side
1075+
commonLabelRect.minX = lx - HOVERARROWSIZE - (HOVERTEXTPAD * 2 + tbb.width);
1076+
commonLabelRect.maxX = lx - HOVERARROWSIZE;
1077+
}
1078+
10511079
var halfHeight = tbb.height / 2;
10521080
var lty = outerTop - tbb.top - halfHeight;
10531081
var clipId = 'clip' + fullLayout._uid + 'commonlabel' + ya._id;
@@ -1090,9 +1118,6 @@ function createHoverText(hoverData, opts) {
10901118
}
10911119

10921120
label.attr('transform', strTranslate(lx, ly));
1093-
1094-
commonLabelLx = lx;
1095-
commonLabelLy = ly;
10961121
});
10971122

10981123
// Show a single hover label
@@ -1411,11 +1436,7 @@ function createHoverText(hoverData, opts) {
14111436

14121437
return {
14131438
hoverLabels: hoverLabels,
1414-
commonLabel: {
1415-
lx: commonLabelLx,
1416-
ly: commonLabelLy,
1417-
label: commonLabel
1418-
}
1439+
commonLabelBoundingBox: commonLabelRect
14191440
};
14201441
}
14211442

@@ -1510,7 +1531,7 @@ function getHoverLabelText(d, showCommonLabel, hovermode, fullLayout, t0, g) {
15101531
// know what happens if the group spans all the way from one edge to
15111532
// the other, though it hardly matters - there's just too much
15121533
// information then.
1513-
function hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, commonLabel) {
1534+
function hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, commonLabelBoundingBox) {
15141535
var axKey = rotateLabels ? 'xa' : 'ya';
15151536
var crossAxKey = rotateLabels ? 'ya' : 'xa';
15161537
var nummoves = 0;
@@ -1522,21 +1543,10 @@ function hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, commonLabel)
15221543
var k = 0;
15231544

15241545
// get extent of axis hover label
1525-
var axisLabelMinX, axisLabelMaxX, axisLabelMinY, axisLabelMaxY;
1526-
if(commonLabel) {
1527-
commonLabel.label.each(function() {
1528-
var selection = d3.select(this);
1529-
if(selection && selection.length && selection[0] && selection[0].length && selection[0][0]) {
1530-
var bbox = selection[0][0].getBBox();
1531-
if(bbox) {
1532-
axisLabelMinX = commonLabel.lx;
1533-
axisLabelMaxX = commonLabel.lx + bbox.width;
1534-
axisLabelMinY = commonLabel.ly;
1535-
axisLabelMaxY = commonLabel.ly + bbox.height;
1536-
}
1537-
}
1538-
});
1539-
}
1546+
var axisLabelMinX = commonLabelBoundingBox.minX;
1547+
var axisLabelMaxX = commonLabelBoundingBox.maxX;
1548+
var axisLabelMinY = commonLabelBoundingBox.minY;
1549+
var axisLabelMaxY = commonLabelBoundingBox.maxY;
15401550

15411551
var pX = function(x) { return x * fullLayout._invScaleX; };
15421552
var pY = function(y) { return y * fullLayout._invScaleY; };

0 commit comments

Comments
 (0)