@@ -156,51 +156,69 @@ module.exports = function plot(gd, calcData) {
156156 if ( gd . _fullLayout . hovermode === false ) return ;
157157 var obj = d . link . trace . link ;
158158 if ( obj . hoverinfo === 'none' || obj . hoverinfo === 'skip' ) return ;
159- var rootBBox = gd . _fullLayout . _paperdiv . node ( ) . getBoundingClientRect ( ) ;
160- var hoverCenterX ;
161- var hoverCenterY ;
162- if ( d . link . circular ) {
163- hoverCenterX = ( d . link . circularPathData . leftInnerExtent + d . link . circularPathData . rightInnerExtent ) / 2 + d . parent . translateX ;
164- hoverCenterY = d . link . circularPathData . verticalFullExtent + d . parent . translateY ;
165- } else {
166- var boundingBox = element . getBoundingClientRect ( ) ;
167- hoverCenterX = boundingBox . left + boundingBox . width / 2 - rootBBox . left ;
168- hoverCenterY = boundingBox . top + boundingBox . height / 2 - rootBBox . top ;
169- }
170159
171- var hovertemplateLabels = { valueLabel : d3 . format ( d . valueFormat ) ( d . link . value ) + d . valueSuffix } ;
172- d . link . fullData = d . link . trace ;
160+ var hoverItems = [ ] ;
173161
174- var tooltip = Fx . loneHover ( {
175- x : hoverCenterX ,
176- y : hoverCenterY ,
177- name : hovertemplateLabels . valueLabel ,
178- text : [
179- d . link . label || '' ,
180- sourceLabel + d . link . source . label ,
181- targetLabel + d . link . target . label ,
182- d . link . concentrationscale ? concentrationLabel + d3 . format ( '%0.2f' ) ( d . link . flow . labelConcentration ) : ''
183- ] . filter ( renderableValuePresent ) . join ( '<br>' ) ,
184- color : castHoverOption ( obj , 'bgcolor' ) || Color . addOpacity ( d . tinyColorHue , 1 ) ,
185- borderColor : castHoverOption ( obj , 'bordercolor' ) ,
186- fontFamily : castHoverOption ( obj , 'font.family' ) ,
187- fontSize : castHoverOption ( obj , 'font.size' ) ,
188- fontColor : castHoverOption ( obj , 'font.color' ) ,
189- idealAlign : d3 . event . x < hoverCenterX ? 'right' : 'left' ,
162+ function hoverCenterPosition ( link ) {
163+ var hoverCenterX , hoverCenterY ;
164+ if ( link . circular ) {
165+ hoverCenterX = ( link . circularPathData . leftInnerExtent + link . circularPathData . rightInnerExtent ) / 2 + d . parent . translateX ;
166+ hoverCenterY = link . circularPathData . verticalFullExtent + d . parent . translateY ;
167+ } else {
168+ hoverCenterX = ( link . source . x1 + link . target . x0 ) / 2 + d . parent . translateX ;
169+ hoverCenterY = ( link . y0 + link . y1 ) / 2 + d . parent . translateY ;
170+ }
171+ return [ hoverCenterX , hoverCenterY ] ;
172+ }
190173
191- hovertemplate : obj . hovertemplate ,
192- hovertemplateLabels : hovertemplateLabels ,
193- eventData : [ d . link ]
194- } , {
174+ // For each related links, create a hoverItem
175+ var anchorIndex = 0 ;
176+ for ( var i = 0 ; i < d . flow . links . length ; i ++ ) {
177+ var link = d . flow . links [ i ] ;
178+ if ( gd . _fullLayout . hovermode === 'closest' && d . link . pointNumber !== link . pointNumber ) continue ;
179+ if ( d . link . pointNumber === link . pointNumber ) anchorIndex = i ;
180+ link . fullData = link . trace ;
181+ obj = d . link . trace . link ;
182+ var hoverCenter = hoverCenterPosition ( link ) ;
183+ var hovertemplateLabels = { valueLabel : d3 . format ( d . valueFormat ) ( link . value ) + d . valueSuffix } ;
184+
185+ hoverItems . push ( {
186+ x : hoverCenter [ 0 ] ,
187+ y : hoverCenter [ 1 ] ,
188+ name : hovertemplateLabels . valueLabel ,
189+ text : [
190+ link . label || '' ,
191+ sourceLabel + link . source . label ,
192+ targetLabel + link . target . label ,
193+ link . concentrationscale ? concentrationLabel + d3 . format ( '%0.2f' ) ( link . flow . labelConcentration ) : ''
194+ ] . filter ( renderableValuePresent ) . join ( '<br>' ) ,
195+ color : castHoverOption ( obj , 'bgcolor' ) || Color . addOpacity ( link . color , 1 ) ,
196+ borderColor : castHoverOption ( obj , 'bordercolor' ) ,
197+ fontFamily : castHoverOption ( obj , 'font.family' ) ,
198+ fontSize : castHoverOption ( obj , 'font.size' ) ,
199+ fontColor : castHoverOption ( obj , 'font.color' ) ,
200+ idealAlign : d3 . event . x < hoverCenter [ 0 ] ? 'right' : 'left' ,
201+
202+ hovertemplate : obj . hovertemplate ,
203+ hovertemplateLabels : hovertemplateLabels ,
204+ eventData : [ link ]
205+ } ) ;
206+ }
207+
208+ var tooltips = Fx . multiHovers ( hoverItems , {
195209 container : fullLayout . _hoverlayer . node ( ) ,
196210 outerContainer : fullLayout . _paper . node ( ) ,
197- gd : gd
211+ gd : gd ,
212+ anchorIndex : anchorIndex
198213 } ) ;
199214
200- if ( ! d . link . concentrationscale ) {
201- makeTranslucent ( tooltip , 0.65 ) ;
202- }
203- makeTextContrasty ( tooltip ) ;
215+ tooltips . each ( function ( ) {
216+ var tooltip = this ;
217+ if ( ! d . link . concentrationscale ) {
218+ makeTranslucent ( tooltip , 0.65 ) ;
219+ }
220+ makeTextContrasty ( tooltip ) ;
221+ } ) ;
204222 } ;
205223
206224 var linkUnhover = function ( element , d , sankey ) {
0 commit comments