Skip to content

Commit 876bd1d

Browse files
committed
put fill hover label at the right (or left) middle.
Finds the outer crossing points at the vertical midline. Note that this will miss curves, if the lines are smoothed, and unlike the contains test there isn't a clean way (far as I know) to get it using browser machinery.
1 parent 8aa4397 commit 876bd1d

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

src/traces/scatter/hover.js

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,50 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
2929
// even if hoveron is 'fills', only use it if we have polygons too
3030
if(trace.hoveron === 'fills' && trace._polygons) {
3131
var polygons = trace._polygons,
32+
polygonsIn = [],
3233
inside = false,
33-
x0 = Infinity,
34-
x1 = -Infinity,
35-
y0 = Infinity,
36-
y1 = -Infinity;
37-
38-
for(var i = 0; i < polygons.length; i++) {
39-
var polygon = polygons[i];
34+
xmin = Infinity,
35+
xmax = -Infinity,
36+
ymin = Infinity,
37+
ymax = -Infinity,
38+
i, j, polygon, pts, xCross, x0, x1, y0, y1;
39+
40+
for(i = 0; i < polygons.length; i++) {
41+
polygon = polygons[i];
4042
// TODO: this is not going to work right for curved edges, it will
4143
// act as though they're straight. That's probably going to need
4244
// the elements themselves to capture the events. Worth it?
4345
if(polygon.contains(pt)) {
4446
inside = !inside;
4547
// TODO: need better than just the overall bounding box
46-
x0 = Math.min(x0, polygon.xmin);
47-
x1 = Math.max(x1, polygon.xmax);
48-
y0 = Math.min(y0, polygon.ymin);
49-
y1 = Math.max(y1, polygon.ymax);
48+
polygonsIn.push(polygon);
49+
ymin = Math.min(ymin, polygon.ymin);
50+
ymax = Math.max(ymax, polygon.ymax);
5051
}
5152
}
5253

5354
if(inside) {
55+
// find the overall left-most and right-most points of the
56+
// polygon(s) we're inside at their combined vertical midpoint.
57+
// This is where we will draw the hover label.
58+
// Note that this might not be the vertical midpoint of the
59+
// whole trace, if it's disjoint.
60+
var yAvg = (ymin + ymax) / 2;
61+
for(i = 0; i < polygonsIn.length; i++) {
62+
pts = polygonsIn[i].pts;
63+
for(j = 1; j < pts.length; j++) {
64+
y0 = pts[j - 1][1];
65+
y1 = pts[j][1];
66+
if((y0 > yAvg) !== (y1 >= yAvg)) {
67+
x0 = pts[j - 1][0];
68+
x1 = pts[j][0];
69+
xCross = x0 + (x1 - x0) * (yAvg - y0) / (y1 - y0);
70+
xmin = Math.min(xmin, xCross);
71+
xmax = Math.max(xmax, xCross);
72+
}
73+
}
74+
}
75+
5476
// get only fill or line color for the hover color
5577
var color = Color.defaultLine;
5678
if(Color.opacity(trace.fillcolor)) color = trace.fillcolor;
@@ -61,14 +83,20 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
6183
Lib.extendFlat(pointData, {
6284
// never let a 2D override 1D type as closest point
6385
distance: constants.MAXDIST + 10,
64-
x0: x0,
65-
x1: x1,
66-
y0: y0,
67-
y1: y1,
86+
x0: xmin,
87+
x1: xmax,
88+
y0: yAvg,
89+
y1: yAvg,
6890
color: color
6991
});
7092

7193
delete pointData.index;
94+
95+
if(trace.text && !Array.isArray(trace.text)) {
96+
pointData.text = String(trace.text);
97+
}
98+
else pointData.text = trace.name;
99+
72100
return [pointData];
73101
}
74102
}

0 commit comments

Comments
 (0)