@@ -31,6 +31,7 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
31
31
var isClosest = ( hovermode === 'closest' ) ;
32
32
var isWaterfall = ( trace . type === 'waterfall' ) ;
33
33
var maxHoverDistance = pointData . maxHoverDistance ;
34
+ var maxSpikeDistance = pointData . maxSpikeDistance ;
34
35
35
36
var posVal , sizeVal , posLetter , sizeLetter , dx , dy , pRangeCalc ;
36
37
@@ -61,40 +62,63 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
61
62
return Math . max ( thisBarMaxPos ( di ) , di . p + t . bardelta / 2 ) ;
62
63
} ;
63
64
64
- function _positionFn ( _minPos , _maxPos ) {
65
+ function hoverPositionFn ( _minPos , _maxPos ) {
65
66
// add a little to the pseudo-distance for wider bars, so that like scatter,
66
67
// if you are over two overlapping bars, the narrower one wins.
67
68
return Fx . inbox ( _minPos - posVal , _maxPos - posVal ,
68
69
maxHoverDistance + Math . min ( 1 , Math . abs ( _maxPos - _minPos ) / pRangeCalc ) - 1 ) ;
69
70
}
70
71
72
+ function spikePositionFn ( _minPos , _maxPos ) {
73
+ // add a little to the pseudo-distance for wider bars, so that like scatter,
74
+ // if you are over two overlapping bars, the narrower one wins.
75
+ return Fx . inbox ( _minPos - posVal , _maxPos - posVal ,
76
+ maxSpikeDistance + Math . min ( 1 , Math . abs ( _maxPos - _minPos ) / pRangeCalc ) - 1 ) ;
77
+ }
78
+
71
79
function positionFn ( di ) {
72
- return _positionFn ( minPos ( di ) , maxPos ( di ) ) ;
80
+ return hoverPositionFn ( minPos ( di ) , maxPos ( di ) ) ;
73
81
}
74
82
75
83
function thisBarPositionFn ( di ) {
76
- return _positionFn ( thisBarMinPos ( di ) , thisBarMaxPos ( di ) ) ;
84
+ return spikePositionFn ( thisBarMinPos ( di ) , thisBarMaxPos ( di ) ) ;
77
85
}
78
86
79
- function sizeFn ( di ) {
80
- var v = sizeVal ;
81
- var b = di . b ;
87
+ function getSize ( di ) {
82
88
var s = di [ sizeLetter ] ;
83
89
84
90
if ( isWaterfall ) {
85
91
var rawS = Math . abs ( di . rawS ) || 0 ;
86
- if ( v > 0 ) {
92
+ if ( sizeVal > 0 ) {
87
93
s += rawS ;
88
- } else if ( v < 0 ) {
94
+ } else if ( sizeVal < 0 ) {
89
95
s -= rawS ;
90
96
}
91
97
}
92
98
99
+ return s ;
100
+ }
101
+
102
+ function sizeFn ( di ) {
103
+ var v = sizeVal ;
104
+ var b = di . b ;
105
+ var s = getSize ( di ) ;
106
+
93
107
// add a gradient so hovering near the end of a
94
108
// bar makes it a little closer match
95
109
return Fx . inbox ( b - v , s - v , maxHoverDistance + ( s - v ) / ( s - b ) - 1 ) ;
96
110
}
97
111
112
+ function thisBarSizeFn ( di ) {
113
+ var v = sizeVal ;
114
+ var b = di . b ;
115
+ var s = getSize ( di ) ;
116
+
117
+ // add a gradient so hovering near the end of a
118
+ // bar makes it a little closer match
119
+ return Fx . inbox ( b - v , s - v , maxSpikeDistance + ( s - v ) / ( s - b ) - 1 ) ;
120
+ }
121
+
98
122
if ( trace . orientation === 'h' ) {
99
123
posVal = yval ;
100
124
sizeVal = xval ;
@@ -158,7 +182,7 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
158
182
pointData . baseLabel = hoverLabelText ( sa , di . b ) ;
159
183
160
184
// spikelines always want "closest" distance regardless of hovermode
161
- pointData . spikeDistance = ( sizeFn ( di ) + thisBarPositionFn ( di ) ) / 2 - maxHoverDistance ;
185
+ pointData . spikeDistance = ( thisBarSizeFn ( di ) + thisBarPositionFn ( di ) ) / 2 ;
162
186
// they also want to point to the data value, regardless of where the label goes
163
187
// in case of bars shifted within groups
164
188
pointData [ posLetter + 'Spike' ] = pa . c2p ( di . p , true ) ;
0 commit comments