Skip to content

Commit 8d627ea

Browse files
committed
show hover tooltip when cursor is anywhere near arrow, not just base point
1 parent f256c63 commit 8d627ea

2 files changed

Lines changed: 39 additions & 4 deletions

File tree

src/traces/quiver/hover.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ var Lib = require('../../lib');
44
var Fx = require('../../components/fx');
55
var getTraceColor = require('../scatter/get_trace_color');
66

7+
// Returns the shortest pixel distance from point (px,py)
8+
// to segment (ax,ay)-(bx,by)
9+
function distToSegment(px, py, ax, ay, bx, by) {
10+
const dx = bx - ax;
11+
const dy = by - ay;
12+
const len2 = dx * dx + dy * dy; // Length of segment (ax,ay)-(bx,by), squared
13+
if(!len2) {
14+
// Zero-length segment, so fall back to point-to-point distance
15+
return Math.sqrt((px - ax) * (px - ax) + (py - ay) * (py - ay));
16+
}
17+
// Compute position of point on segment which is closest to (px,py) -> call it (cx, cy)
18+
var t = ((px - ax) * dx + (py - ay) * dy) / len2;
19+
t = Math.max(0, Math.min(1, t));
20+
const cx = ax + t * dx;
21+
const cy = ay + t * dy;
22+
// Compute distance from (px,py) to (cx,cy)
23+
return Math.sqrt((px - cx) * (px - cx) + (py - cy) * (py - cy));
24+
}
25+
726
module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
827
var cd = pointData.cd;
928
var trace = cd[0].trace;
@@ -12,10 +31,15 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
1231
var xpx = xa.c2p(xval);
1332
var ypx = ya.c2p(yval);
1433

34+
// Check distance from the whole arrow body (base -> tip)
35+
// rather than only the (x,y) data position of the arrow
1536
var distfn = function(di) {
16-
var x = xa.c2p(di.x) - xpx;
17-
var y = ya.c2p(di.y) - ypx;
18-
return Math.sqrt(x * x + y * y);
37+
if(di._x0 === undefined) return Infinity;
38+
var ax0 = xa.c2p(di._x0);
39+
var ay0 = ya.c2p(di._y0);
40+
var ax1 = xa.c2p(di._x1);
41+
var ay1 = ya.c2p(di._y1);
42+
return distToSegment(xpx, ypx, ax0, ay0, ax1, ay1);
1943
};
2044

2145
Fx.getClosest(cd, distfn, pointData);
@@ -28,6 +52,9 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
2852
var xc = xa.c2p(di.x, true);
2953
var yc = ya.c2p(di.y, true);
3054

55+
// Compute distance from cursor to the base point (x,y) of the arrow
56+
var distToPoint = Math.sqrt((xpx - xc) * (xpx - xc) + (ypx - yc) * (ypx - yc));
57+
3158
// now we're done using the whole `calcdata` array, replace the
3259
// index with the original index
3360
pointData.index = di.i;
@@ -54,7 +81,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
5481

5582
extraText: extraText,
5683

57-
spikeDistance: Math.sqrt((xpx - xc) * (xpx - xc) + (ypx - yc) * (ypx - yc)),
84+
spikeDistance: distToPoint,
5885
hovertemplate: trace.hovertemplate
5986
});
6087

src/traces/quiver/plot.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
156156
y1 = y0 + dy;
157157
}
158158

159+
// Store the arrow body endpoints in calcData so that
160+
// hovertext can be shown based on distance to the whole arrow segment,
161+
// not just the base point (x,y)
162+
cdi._x0 = x0;
163+
cdi._y0 = y0;
164+
cdi._x1 = x1;
165+
cdi._y1 = y1;
166+
159167
// Arrow body endpoints (px)
160168
const p0x = xa.c2p(x0);
161169
const p0y = ya.c2p(y0);

0 commit comments

Comments
 (0)