@@ -209,14 +209,15 @@ exports.loneHover = function loneHover(hoverItems, opts) {
209209
210210 var rotateLabels = false ;
211211
212- var hoverLabel = createHoverText ( pointsData , {
212+ var hoverText = createHoverText ( pointsData , {
213213 gd : gd ,
214214 hovermode : 'closest' ,
215215 rotateLabels : rotateLabels ,
216216 bgColor : opts . bgColor || Color . background ,
217217 container : d3 . select ( opts . container ) ,
218218 outerContainer : opts . outerContainer || opts . container
219219 } ) ;
220+ var hoverLabel = hoverText . hoverLabels ;
220221
221222 // Fix vertical overlap
222223 var tooltipSpacing = 5 ;
@@ -819,7 +820,7 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
819820 fullLayout . paper_bgcolor
820821 ) ;
821822
822- var hoverLabels = createHoverText ( hoverData , {
823+ var hoverText = createHoverText ( hoverData , {
823824 gd : gd ,
824825 hovermode : hovermode ,
825826 rotateLabels : rotateLabels ,
@@ -829,9 +830,10 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
829830 commonLabelOpts : fullLayout . hoverlabel ,
830831 hoverdistance : fullLayout . hoverdistance
831832 } ) ;
833+ var hoverLabels = hoverText . hoverLabels ;
832834
833835 if ( ! helpers . isUnifiedHover ( hovermode ) ) {
834- hoverAvoidOverlaps ( hoverLabels , rotateLabels ? 'xa' : 'ya' , fullLayout ) ;
836+ hoverAvoidOverlaps ( hoverLabels , rotateLabels ? 'xa' : 'ya' , fullLayout , hoverText . commonLabel ) ;
835837 alignHoverText ( hoverLabels , rotateLabels , fullLayout . _invScaleX , fullLayout . _invScaleY ) ;
836838 } // TODO: tagName hack is needed to appease geo.js's hack of using eventTarget=true
837839 // we should improve the "fx" API so other plots can use it without these hack.
@@ -942,6 +944,7 @@ function createHoverText(hoverData, opts) {
942944 . classed ( 'axistext' , true ) ;
943945 commonLabel . exit ( ) . remove ( ) ;
944946
947+ var commonLabelLx , commonLabelLy ;
945948 commonLabel . each ( function ( ) {
946949 var label = d3 . select ( this ) ;
947950 var lpath = Lib . ensureSingle ( label , 'path' , '' , function ( s ) {
@@ -1087,6 +1090,9 @@ function createHoverText(hoverData, opts) {
10871090 }
10881091
10891092 label . attr ( 'transform' , strTranslate ( lx , ly ) ) ;
1093+
1094+ commonLabelLx = lx ;
1095+ commonLabelLy = ly ;
10901096 } ) ;
10911097
10921098 // Show a single hover label
@@ -1370,7 +1376,10 @@ function createHoverText(hoverData, opts) {
13701376 } else if ( anchorStartOK ) {
13711377 hty += dy / 2 ;
13721378 d . anchor = 'start' ;
1373- } else d . anchor = 'middle' ;
1379+ } else {
1380+ d . anchor = 'middle' ;
1381+ }
1382+ d . crossPos = hty ;
13741383 } else {
13751384 d . pos = hty ;
13761385 anchorStartOK = htx + dx / 2 + txTotalWidth <= outerWidth ;
@@ -1391,6 +1400,7 @@ function createHoverText(hoverData, opts) {
13911400 if ( overflowR > 0 ) htx -= overflowR ;
13921401 if ( overflowL < 0 ) htx += - overflowL ;
13931402 }
1403+ d . crossPos = htx ;
13941404 }
13951405
13961406 tx . attr ( 'text-anchor' , d . anchor ) ;
@@ -1399,7 +1409,14 @@ function createHoverText(hoverData, opts) {
13991409 ( rotateLabels ? strRotate ( YANGLE ) : '' ) ) ;
14001410 } ) ;
14011411
1402- return hoverLabels ;
1412+ return {
1413+ hoverLabels : hoverLabels ,
1414+ commonLabel : {
1415+ lx : commonLabelLx ,
1416+ ly : commonLabelLy ,
1417+ label : commonLabel
1418+ }
1419+ } ;
14031420}
14041421
14051422function getHoverLabelText ( d , showCommonLabel , hovermode , fullLayout , t0 , g ) {
@@ -1493,7 +1510,7 @@ function getHoverLabelText(d, showCommonLabel, hovermode, fullLayout, t0, g) {
14931510// know what happens if the group spans all the way from one edge to
14941511// the other, though it hardly matters - there's just too much
14951512// information then.
1496- function hoverAvoidOverlaps ( hoverLabels , axKey , fullLayout ) {
1513+ function hoverAvoidOverlaps ( hoverLabels , axKey , fullLayout , commonLabel ) {
14971514 var crossAxKey = axKey === 'xa' ? 'ya' : 'xa' ;
14981515 var nummoves = 0 ;
14991516 var axSign = 1 ;
@@ -1503,6 +1520,27 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout) {
15031520 var pointgroups = new Array ( nLabels ) ;
15041521 var k = 0 ;
15051522
1523+ // get extent of axis hover label
1524+ var axisLabelMinX , axisLabelMaxX , axisLabelMinY , axisLabelMaxY ;
1525+ if ( commonLabel ) {
1526+ commonLabel . label . each ( function ( ) {
1527+ 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+ }
1539+ }
1540+ }
1541+ } ) ;
1542+ }
1543+
15061544 hoverLabels . each ( function ( d ) {
15071545 var ax = d [ axKey ] ;
15081546 var crossAx = d [ crossAxKey ] ;
@@ -1514,20 +1552,29 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout) {
15141552 }
15151553 var pmin = 0 ;
15161554 var pmax = ( axIsX ? fullLayout . width : fullLayout . height ) ;
1517- if ( fullLayout . hovermode === 'x' || fullLayout . hovermode === 'y' ) {
1518- if ( axIsX ) {
1519- if ( crossAx . side === 'left' ) {
1520- pmin = crossAx . _mainLinePosition ;
1521- pmax = fullLayout . width ;
1522- } else {
1523- pmax = crossAx . _mainLinePosition ;
1555+ 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 ;
1559+ if ( axIsX ) {
1560+ if ( Math . max ( labelMinX , axisLabelMinY ) <= Math . min ( labelMaxX , axisLabelMaxY ) ) {
1561+ // has overlap with axis label
1562+ if ( crossAx . side === 'left' ) {
1563+ pmin = crossAx . _mainLinePosition ;
1564+ pmax = fullLayout . width ;
1565+ } else {
1566+ pmax = crossAx . _mainLinePosition ;
1567+ }
15241568 }
15251569 } else {
1526- if ( crossAx . side === 'top' ) {
1527- pmin = crossAx . _mainLinePosition ;
1528- pmax = fullLayout . height ;
1529- } else {
1530- pmax = crossAx . _mainLinePosition ;
1570+ if ( Math . max ( labelMinX , axisLabelMinX ) <= Math . min ( labelMaxX , axisLabelMaxX ) ) {
1571+ // has overlap with axis label
1572+ if ( crossAx . side === 'top' ) {
1573+ pmin = crossAx . _mainLinePosition ;
1574+ pmax = fullLayout . height ;
1575+ } else {
1576+ pmax = crossAx . _mainLinePosition ;
1577+ }
15311578 }
15321579 }
15331580 }
@@ -1539,8 +1586,8 @@ function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout) {
15391586 pos : d . pos ,
15401587 posref : d . posref ,
15411588 size : d . by * ( axIsX ? YFACTOR : 1 ) / 2 ,
1542- pmin,
1543- pmax
1589+ pmin : pmin ,
1590+ pmax : pmax
15441591 } ] ;
15451592 } ) ;
15461593
0 commit comments