@@ -46,6 +46,12 @@ var multipleHoverPoints = {
4646 candlestick : true
4747} ;
4848
49+ var cartesianScatterPoints = {
50+ scatter : true ,
51+ scattergl : true ,
52+ splom : true
53+ } ;
54+
4955// fx.hover: highlight data on hover
5056// evt can be a mousemove event, or an object with data about what points
5157// to hover on
@@ -574,12 +580,15 @@ function _hover(gd, evt, subplot, noHoverEvent) {
574580
575581 findHoverPoints ( ) ;
576582
577- function selectClosestPoint ( pointsData , spikedistance ) {
583+ function selectClosestPoint ( pointsData , spikedistance , spikeOnWinning ) {
578584 var resultPoint = null ;
579585 var minDistance = Infinity ;
580586 var thisSpikeDistance ;
587+
581588 for ( var i = 0 ; i < pointsData . length ; i ++ ) {
582589 thisSpikeDistance = pointsData [ i ] . spikeDistance ;
590+ if ( spikeOnWinning && i === 0 ) thisSpikeDistance = - Infinity ;
591+
583592 if ( thisSpikeDistance <= minDistance && thisSpikeDistance <= spikedistance ) {
584593 resultPoint = pointsData [ i ] ;
585594 minDistance = thisSpikeDistance ;
@@ -616,19 +625,30 @@ function _hover(gd, evt, subplot, noHoverEvent) {
616625 } ;
617626 gd . _spikepoints = newspikepoints ;
618627
628+ var sortHoverData = function ( ) {
629+ hoverData . sort ( function ( d1 , d2 ) { return d1 . distance - d2 . distance ; } ) ;
630+
631+ // move period positioned points and box/bar-like traces to the end of the list
632+ hoverData = orderRangePoints ( hoverData , hovermode ) ;
633+ } ;
634+ sortHoverData ( ) ;
635+
636+ var axLetter = hovermode . charAt ( 0 ) ;
637+ var spikeOnWinning = ( axLetter === 'x' || axLetter === 'y' ) && hoverData [ 0 ] && cartesianScatterPoints [ hoverData [ 0 ] . trace . type ] ;
638+
619639 // Now if it is not restricted by spikedistance option, set the points to draw the spikelines
620640 if ( hasCartesian && ( spikedistance !== 0 ) ) {
621641 if ( hoverData . length !== 0 ) {
622642 var tmpHPointData = hoverData . filter ( function ( point ) {
623643 return point . ya . showspikes ;
624644 } ) ;
625- var tmpHPoint = selectClosestPoint ( tmpHPointData , spikedistance ) ;
645+ var tmpHPoint = selectClosestPoint ( tmpHPointData , spikedistance , spikeOnWinning ) ;
626646 spikePoints . hLinePoint = fillSpikePoint ( tmpHPoint ) ;
627647
628648 var tmpVPointData = hoverData . filter ( function ( point ) {
629649 return point . xa . showspikes ;
630650 } ) ;
631- var tmpVPoint = selectClosestPoint ( tmpVPointData , spikedistance ) ;
651+ var tmpVPoint = selectClosestPoint ( tmpVPointData , spikedistance , spikeOnWinning ) ;
632652 spikePoints . vLinePoint = fillSpikePoint ( tmpVPoint ) ;
633653 }
634654 }
@@ -650,14 +670,6 @@ function _hover(gd, evt, subplot, noHoverEvent) {
650670 }
651671 }
652672
653- var sortHoverData = function ( ) {
654- hoverData . sort ( function ( d1 , d2 ) { return d1 . distance - d2 . distance ; } ) ;
655-
656- // move period positioned points and box/bar-like traces to the end of the list
657- hoverData = orderRangePoints ( hoverData , hovermode ) ;
658- } ;
659- sortHoverData ( ) ;
660-
661673 if (
662674 helpers . isXYhover ( _mode ) &&
663675 hoverData [ 0 ] . length !== 0 &&
@@ -1074,7 +1086,7 @@ function createHoverText(hoverData, opts, gd) {
10741086 var winningPoint = hoverData [ 0 ] ;
10751087
10761088 // When the scatter point wins, it's OK for the hovelabel to occlude the bar and other points.
1077- var scatterWon = winningPoint . trace . type === 'scatter' ;
1089+ var scatterWon = cartesianScatterPoints [ winningPoint . trace . type ] ;
10781090
10791091 var lyBottom , lyTop ;
10801092 if ( axLetter === 'y' ) {
0 commit comments