@@ -4,6 +4,25 @@ var Lib = require('../../lib');
44var Fx = require ( '../../components/fx' ) ;
55var 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+
726module . 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
0 commit comments