@@ -833,7 +833,7 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
833833 var hoverLabels = hoverText . hoverLabels ;
834834
835835 if ( ! helpers . isUnifiedHover ( hovermode ) ) {
836- hoverAvoidOverlaps ( hoverLabels , rotateLabels ? 'xa' : 'ya' , fullLayout , hoverText . commonLabel ) ;
836+ hoverAvoidOverlaps ( hoverLabels , rotateLabels , fullLayout , hoverText . commonLabel ) ;
837837 alignHoverText ( hoverLabels , rotateLabels , fullLayout . _invScaleX , fullLayout . _invScaleY ) ;
838838 } // TODO: tagName hack is needed to appease geo.js's hack of using eventTarget=true
839839 // we should improve the "fx" API so other plots can use it without these hack.
@@ -1510,8 +1510,9 @@ function getHoverLabelText(d, showCommonLabel, hovermode, fullLayout, t0, g) {
15101510// know what happens if the group spans all the way from one edge to
15111511// the other, though it hardly matters - there's just too much
15121512// information then.
1513- function hoverAvoidOverlaps ( hoverLabels , axKey , fullLayout , commonLabel ) {
1514- var crossAxKey = axKey === 'xa' ? 'ya' : 'xa' ;
1513+ function hoverAvoidOverlaps ( hoverLabels , rotateLabels , fullLayout , commonLabel ) {
1514+ var axKey = rotateLabels ? 'xa' : 'ya' ;
1515+ var crossAxKey = rotateLabels ? 'ya' : 'xa' ;
15151516 var nummoves = 0 ;
15161517 var axSign = 1 ;
15171518 var nLabels = hoverLabels . size ( ) ;
@@ -1525,17 +1526,13 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout, commonLabel) {
15251526 if ( commonLabel ) {
15261527 commonLabel . label . each ( function ( ) {
15271528 var selection = d3 . select ( this ) ;
1528- if ( selection && selection . length ) {
1529- var labels = selection [ 0 ] ;
1530- if ( labels && labels . length ) {
1531- var label = labels [ 0 ] ;
1532- var bbox = label . getBBox ( ) ;
1533- if ( bbox ) {
1534- axisLabelMinX = commonLabel . lx ;
1535- axisLabelMaxX = commonLabel . lx + bbox . width ;
1536- axisLabelMinY = commonLabel . ly ;
1537- axisLabelMaxY = commonLabel . ly + bbox . height ;
1538- }
1529+ if ( selection && selection . length && selection [ 0 ] && selection [ 0 ] . length && selection [ 0 ] [ 0 ] ) {
1530+ var bbox = selection [ 0 ] [ 0 ] . getBBox ( ) ;
1531+ if ( bbox ) {
1532+ axisLabelMinX = commonLabel . lx ;
1533+ axisLabelMaxX = commonLabel . lx + bbox . width ;
1534+ axisLabelMinY = commonLabel . ly ;
1535+ axisLabelMaxY = commonLabel . ly + bbox . height ;
15391536 }
15401537 }
15411538 } ) ;
@@ -1553,11 +1550,16 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout, commonLabel) {
15531550 var pmin = 0 ;
15541551 var pmax = ( axIsX ? fullLayout . width : fullLayout . height ) ;
15551552 if ( fullLayout . hovermode === 'x' || fullLayout . hovermode === 'y' ) {
1556- // extent of hover label on cross axis:
1557- var labelMinX = d . crossPos ;
1558- var labelMaxX = d . crossPos + d . txwidth ;
1553+ // extent of rect behind hover label on cross axis (without arrow):
1554+ var offsets = getHoverLabelOffsets ( d , rotateLabels ) ;
1555+ var shiftX = getLabelShiftX ( d ) ;
1556+ // calculation based on alignHoverText function
1557+ var offsetRectX = ( shiftX . x2x + ( shiftX . alignShift - 1 ) * d . tx2width / 2 + offsets . x ) * fullLayout . _invScaleX ;
1558+
1559+ var labelMinX = d . crossPos + offsetRectX ;
1560+ var labelMaxX = labelMinX + d . tx2width ;
15591561 if ( axIsX ) {
1560- if ( Math . max ( labelMinX , axisLabelMinY ) <= Math . min ( labelMaxX , axisLabelMaxY ) ) {
1562+ if ( axisLabelMinY !== undefined && axisLabelMaxY !== undefined && Math . max ( labelMinX , axisLabelMinY ) <= Math . min ( labelMaxX , axisLabelMaxY ) ) {
15611563 // has overlap with axis label
15621564 if ( crossAx . side === 'left' ) {
15631565 pmin = crossAx . _mainLinePosition ;
@@ -1567,7 +1569,7 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout, commonLabel) {
15671569 }
15681570 }
15691571 } else {
1570- if ( Math . max ( labelMinX , axisLabelMinX ) <= Math . min ( labelMaxX , axisLabelMaxX ) ) {
1572+ if ( axisLabelMinX !== undefined && axisLabelMaxX !== undefined && Math . max ( labelMinX , axisLabelMinX ) <= Math . min ( labelMaxX , axisLabelMaxX ) ) {
15711573 // has overlap with axis label
15721574 if ( crossAx . side === 'top' ) {
15731575 pmin = crossAx . _mainLinePosition ;
@@ -1731,6 +1733,39 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout, commonLabel) {
17311733 }
17321734}
17331735
1736+ function getHoverLabelOffsets ( hoverLabel , rotateLabels ) {
1737+ var offsetX = 0 ;
1738+ var offsetY = hoverLabel . offset ;
1739+
1740+ if ( rotateLabels ) {
1741+ offsetY *= - YSHIFTY ;
1742+ offsetX = hoverLabel . offset * YSHIFTX ;
1743+ }
1744+
1745+ return {
1746+ x : offsetX ,
1747+ y : offsetY
1748+ } ;
1749+ }
1750+
1751+ function getLabelShiftX ( hoverLabel ) {
1752+ var alignShift = { start : 1 , end : - 1 , middle : 0 } [ hoverLabel . anchor ] ;
1753+ var txx = alignShift * ( HOVERARROWSIZE + HOVERTEXTPAD ) ;
1754+ var tx2x = txx + alignShift * ( hoverLabel . txwidth + HOVERTEXTPAD ) ;
1755+
1756+ var isMiddle = hoverLabel . anchor === 'middle' ;
1757+ if ( isMiddle ) {
1758+ txx -= hoverLabel . tx2width / 2 ;
1759+ tx2x += hoverLabel . txwidth / 2 + HOVERTEXTPAD ;
1760+ }
1761+
1762+ return {
1763+ alignShift : alignShift ,
1764+ xx : txx ,
1765+ x2x : tx2x
1766+ } ;
1767+ }
1768+
17341769function alignHoverText ( hoverLabels , rotateLabels , scaleX , scaleY ) {
17351770 var pX = function ( x ) { return x * scaleX ; } ;
17361771 var pY = function ( y ) { return y * scaleY ; } ;
@@ -1744,38 +1779,27 @@ function alignHoverText(hoverLabels, rotateLabels, scaleX, scaleY) {
17441779 var tx = g . select ( 'text.nums' ) ;
17451780 var anchor = d . anchor ;
17461781 var horzSign = anchor === 'end' ? - 1 : 1 ;
1747- var alignShift = { start : 1 , end : - 1 , middle : 0 } [ anchor ] ;
1748- var txx = alignShift * ( HOVERARROWSIZE + HOVERTEXTPAD ) ;
1749- var tx2x = txx + alignShift * ( d . txwidth + HOVERTEXTPAD ) ;
1750- var offsetX = 0 ;
1751- var offsetY = d . offset ;
1782+ var shiftX = getLabelShiftX ( d ) ;
1783+ var offsets = getHoverLabelOffsets ( d , rotateLabels ) ;
17521784
17531785 var isMiddle = anchor === 'middle' ;
1754- if ( isMiddle ) {
1755- txx -= d . tx2width / 2 ;
1756- tx2x += d . txwidth / 2 + HOVERTEXTPAD ;
1757- }
1758- if ( rotateLabels ) {
1759- offsetY *= - YSHIFTY ;
1760- offsetX = d . offset * YSHIFTX ;
1761- }
17621786
17631787 g . select ( 'path' )
17641788 . attr ( 'd' , isMiddle ?
17651789 // middle aligned: rect centered on data
1766- ( 'M-' + pX ( d . bx / 2 + d . tx2width / 2 ) + ',' + pY ( offsetY - d . by / 2 ) +
1790+ ( 'M-' + pX ( d . bx / 2 + d . tx2width / 2 ) + ',' + pY ( offsets . y - d . by / 2 ) +
17671791 'h' + pX ( d . bx ) + 'v' + pY ( d . by ) + 'h-' + pX ( d . bx ) + 'Z' ) :
17681792 // left or right aligned: side rect with arrow to data
1769- ( 'M0,0L' + pX ( horzSign * HOVERARROWSIZE + offsetX ) + ',' + pY ( HOVERARROWSIZE + offsetY ) +
1793+ ( 'M0,0L' + pX ( horzSign * HOVERARROWSIZE + offsets . x ) + ',' + pY ( HOVERARROWSIZE + offsets . y ) +
17701794 'v' + pY ( d . by / 2 - HOVERARROWSIZE ) +
17711795 'h' + pX ( horzSign * d . bx ) +
17721796 'v-' + pY ( d . by ) +
1773- 'H' + pX ( horzSign * HOVERARROWSIZE + offsetX ) +
1774- 'V' + pY ( offsetY - HOVERARROWSIZE ) +
1797+ 'H' + pX ( horzSign * HOVERARROWSIZE + offsets . x ) +
1798+ 'V' + pY ( offsets . y - HOVERARROWSIZE ) +
17751799 'Z' ) ) ;
17761800
1777- var posX = offsetX + txx ;
1778- var posY = offsetY + d . ty0 - d . by / 2 + HOVERTEXTPAD ;
1801+ var posX = offsets . x + shiftX . xx ;
1802+ var posY = offsets . y + d . ty0 - d . by / 2 + HOVERTEXTPAD ;
17791803 var textAlign = d . textAlign || 'auto' ;
17801804
17811805 if ( textAlign !== 'auto' ) {
@@ -1797,12 +1821,12 @@ function alignHoverText(hoverLabels, rotateLabels, scaleX, scaleY) {
17971821 if ( d . tx2width ) {
17981822 g . select ( 'text.name' )
17991823 . call ( svgTextUtils . positionText ,
1800- pX ( tx2x + alignShift * HOVERTEXTPAD + offsetX ) ,
1801- pY ( offsetY + d . ty0 - d . by / 2 + HOVERTEXTPAD ) ) ;
1824+ pX ( shiftX . x2x + shiftX . alignShift * HOVERTEXTPAD + offsets . x ) ,
1825+ pY ( offsets . y + d . ty0 - d . by / 2 + HOVERTEXTPAD ) ) ;
18021826 g . select ( 'rect' )
18031827 . call ( Drawing . setRect ,
1804- pX ( tx2x + ( alignShift - 1 ) * d . tx2width / 2 + offsetX ) ,
1805- pY ( offsetY - d . by / 2 - 1 ) ,
1828+ pX ( shiftX . x2x + ( shiftX . alignShift - 1 ) * d . tx2width / 2 + offsets . x ) ,
1829+ pY ( offsets . y - d . by / 2 - 1 ) ,
18061830 pX ( d . tx2width ) , pY ( d . by + 2 ) ) ;
18071831 }
18081832 } ) ;
0 commit comments