@@ -790,41 +790,80 @@ function createHoverText(hoverData, opts, gd) {
790790 label . attr ( 'transform' , '' ) ;
791791
792792 var tbb = ltext . node ( ) . getBoundingClientRect ( ) ;
793+ var lx , ly ;
794+
793795 if ( hovermode === 'x' ) {
796+ var topsign = xa . side === 'top' ? '-' : '' ;
797+
794798 ltext . attr ( 'text-anchor' , 'middle' )
795799 . call ( svgTextUtils . positionText , 0 , ( xa . side === 'top' ?
796800 ( outerTop - tbb . bottom - HOVERARROWSIZE - HOVERTEXTPAD ) :
797801 ( outerTop - tbb . top + HOVERARROWSIZE + HOVERTEXTPAD ) ) ) ;
798802
799- var topsign = xa . side === 'top' ? '-' : '' ;
800- lpath . attr ( 'd' , 'M0,0' +
801- 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE +
802- 'H' + ( HOVERTEXTPAD + tbb . width / 2 ) +
803- 'v' + topsign + ( HOVERTEXTPAD * 2 + tbb . height ) +
804- 'H-' + ( HOVERTEXTPAD + tbb . width / 2 ) +
805- 'V' + topsign + HOVERARROWSIZE + 'H-' + HOVERARROWSIZE + 'Z' ) ;
806-
807- label . attr ( 'transform' , 'translate(' +
808- ( xa . _offset + ( c0 . x0 + c0 . x1 ) / 2 ) + ',' +
809- ( ya . _offset + ( xa . side === 'top' ? 0 : ya . _length ) ) + ')' ) ;
803+ lx = xa . _offset + ( c0 . x0 + c0 . x1 ) / 2 ;
804+ ly = ya . _offset + ( xa . side === 'top' ? 0 : ya . _length ) ;
805+
806+ var halfWidth = tbb . width / 2 + HOVERTEXTPAD ;
807+
808+ if ( lx < halfWidth ) {
809+ lx = halfWidth ;
810+
811+ lpath . attr ( 'd' , 'M-' + ( halfWidth - HOVERARROWSIZE ) + ',0' +
812+ 'L-' + ( halfWidth - HOVERARROWSIZE * 2 ) + ',' + topsign + HOVERARROWSIZE +
813+ 'H' + ( HOVERTEXTPAD + tbb . width / 2 ) +
814+ 'v' + topsign + ( HOVERTEXTPAD * 2 + tbb . height ) +
815+ 'H-' + halfWidth +
816+ 'V' + topsign + HOVERARROWSIZE +
817+ 'Z' ) ;
818+ } else if ( lx > ( fullLayout . width - halfWidth ) ) {
819+ lx = fullLayout . width - halfWidth ;
820+
821+ lpath . attr ( 'd' , 'M' + ( halfWidth - HOVERARROWSIZE ) + ',0' +
822+ 'L' + halfWidth + ',' + topsign + HOVERARROWSIZE +
823+ 'v' + topsign + ( HOVERTEXTPAD * 2 + tbb . height ) +
824+ 'H-' + halfWidth +
825+ 'V' + topsign + HOVERARROWSIZE +
826+ 'H' + ( halfWidth - HOVERARROWSIZE * 2 ) + 'Z' ) ;
827+ } else {
828+ lpath . attr ( 'd' , 'M0,0' +
829+ 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE +
830+ 'H' + ( HOVERTEXTPAD + tbb . width / 2 ) +
831+ 'v' + topsign + ( HOVERTEXTPAD * 2 + tbb . height ) +
832+ 'H-' + ( HOVERTEXTPAD + tbb . width / 2 ) +
833+ 'V' + topsign + HOVERARROWSIZE +
834+ 'H-' + HOVERARROWSIZE + 'Z' ) ;
835+ }
810836 } else {
811- ltext . attr ( 'text-anchor' , ya . side === 'right' ? 'start' : 'end' )
812- . call ( svgTextUtils . positionText ,
813- ( ya . side === 'right' ? 1 : - 1 ) * ( HOVERTEXTPAD + HOVERARROWSIZE ) ,
814- outerTop - tbb . top - tbb . height / 2 ) ;
837+ var anchor ;
838+ var sgn ;
839+ var leftsign ;
840+ if ( ya . side === 'right' ) {
841+ anchor = 'start' ;
842+ sgn = 1 ;
843+ leftsign = '' ;
844+ lx = xa . _offset + xa . _length ;
845+ } else {
846+ anchor = 'end' ;
847+ sgn = - 1 ;
848+ leftsign = '-' ;
849+ lx = xa . _offset ;
850+ }
851+
852+ ly = ya . _offset + ( c0 . y0 + c0 . y1 ) / 2 ;
853+
854+ ltext . attr ( 'text-anchor' , anchor ) ;
815855
816- var leftsign = ya . side === 'right' ? '' : '-' ;
817856 lpath . attr ( 'd' , 'M0,0' +
818857 'L' + leftsign + HOVERARROWSIZE + ',' + HOVERARROWSIZE +
819858 'V' + ( HOVERTEXTPAD + tbb . height / 2 ) +
820859 'h' + leftsign + ( HOVERTEXTPAD * 2 + tbb . width ) +
821860 'V-' + ( HOVERTEXTPAD + tbb . height / 2 ) +
822861 'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z' ) ;
823862
824- label . attr ( 'transform' , 'translate(' +
825- ( xa . _offset + ( ya . side === 'right' ? xa . _length : 0 ) ) + ',' +
826- ( ya . _offset + ( c0 . y0 + c0 . y1 ) / 2 ) + ')' ) ;
827863 }
864+
865+ label . attr ( 'transform' , 'translate(' + lx + ',' + ly + ')' ) ;
866+
828867 // remove the "close but not quite" points
829868 // because of error bars, only take up to a space
830869 hoverData = hoverData . filter ( function ( d ) {
0 commit comments