@@ -467,6 +467,7 @@ function renderPie(
467467
468468 let pie = d3 . pie ( ) ;
469469 let pieValues = pie ( values ) ;
470+ pieValues . forEach ( function ( value : any , i : number ) { value . input_index = i } )
470471
471472 let sectors = sectorsGroup
472473 . selectAll ( "sector" )
@@ -526,36 +527,72 @@ function renderPie(
526527 return arcObj . startAngle + ( arcObj . endAngle - arcObj . startAngle ) / 2 ;
527528 }
528529
530+ function externalLabelText ( arcObj : any , i : number ) {
531+ if ( showExtLabelOnlyIfNoLabel ) {
532+ if ( labels [ i ] === "" || isLabelHidden ( arcObj ) ) {
533+ return extLabels [ i ] ;
534+ }
535+ return "" ;
536+ } else {
537+ return extLabels [ i ] ;
538+ }
539+ }
540+
529541 // external label elements
542+ let prevBB : DOMRect = null ;
543+ let extlabelPos : any = { } ;
530544 let extLabelElements = sectorsGroup
531545 . selectAll ( "extLabel" )
532546 . data ( pieValues )
533547 . enter ( )
534548 . append ( "text" )
549+ // Sort external labels based on y value such that we can move down overlapping labels
550+ . sort ( function ( arcObj1 : any , arcObj2 : any ) {
551+ return Math . cos ( getMidAngle ( arcObj2 ) ) - Math . cos ( getMidAngle ( arcObj1 ) ) ;
552+ } )
535553 . text ( function ( arcObj : any , i : number ) {
536- if ( showExtLabelOnlyIfNoLabel ) {
537- if ( labels [ i ] === "" || isLabelHidden ( arcObj ) ) {
538- return extLabels [ i ] ;
539- }
540- return "" ;
541- } else {
542- return extLabels [ i ] ;
543- }
554+ i = arcObj . input_index ;
555+ return externalLabelText ( arcObj , i )
544556 } )
545557 . attr ( "transform" , function ( arcObj : any , i : number ) {
558+ i = arcObj . input_index ;
559+ // If external label is empty, directly return.
560+ if ( externalLabelText ( arcObj , i ) . length == 0 ) {
561+ return ;
562+ }
546563 let posLabel = hiddenArc . centroid ( arcObj ) ;
547564 let midAngle = getMidAngle ( arcObj ) ;
548565
549566 posLabel [ 0 ] =
550567 ( radius * 0.99 - extLabelSizes [ i ] . width ) *
551568 ( midAngle < Math . PI ? 1 : - 1 ) ;
552- return "translate(" + posLabel [ 0 ] + "," + posLabel [ 1 ] + ")" ;
569+
570+ var yshift = 0 ;
571+ let thisBB = new DOMRect ( posLabel [ 0 ] , posLabel [ 1 ] , extLabelSizes [ i ] . width , extLabelSizes [ i ] . height ) ;
572+
573+ if ( prevBB !== null ) {
574+ // Check whether there are overlaps
575+ if ( ! ( thisBB . right < prevBB . left || prevBB . right < thisBB . left
576+ || prevBB . bottom < thisBB . top ) ) {
577+ // Since y is sorted from low to high, we expect to shift this item further down
578+ yshift = prevBB . bottom - thisBB . top ;
579+ // console.log("has overlap", yshift);
580+ }
581+ }
582+ if ( yshift != 0 ) {
583+ thisBB = new DOMRect ( posLabel [ 0 ] , posLabel [ 1 ] + yshift , extLabelSizes [ i ] . width , extLabelSizes [ i ] . height ) ;
584+ }
585+ prevBB = thisBB ;
586+ // Save external label position for connection line plotting
587+ extlabelPos [ i ] = [ posLabel [ 0 ] , posLabel [ 1 ] + yshift ]
588+ return "translate(" + posLabel [ 0 ] + "," + ( posLabel [ 1 ] + yshift ) + ")" ;
553589 } )
554590 . style ( "text-anchor" , function ( arcObj : any ) {
555591 let midAngle = getMidAngle ( arcObj ) ;
556592 return midAngle < Math . PI ? "start" : "end" ;
557593 } )
558594 . attr ( "class" , "tracker-pie-label" ) ;
595+
559596
560597 function getPointsForConnectionLines ( arcObj : any , i : number ) {
561598 let labelWidth = labelSizes [ i ] . width ;
@@ -565,7 +602,8 @@ function renderPie(
565602
566603 let posLabel = arc . centroid ( arcObj ) ; // line insertion in the slice
567604 let posMiddle = hiddenArc . centroid ( arcObj ) ; // line break: we use the other arc generator that has been built only for that
568- let posExtLabel = hiddenArc . centroid ( arcObj ) ; // Label position = almost the same as posB
605+ let posExtLabel = extlabelPos [ i ] || hiddenArc . centroid ( arcObj ) ; // Label position = almost the same as posB
606+ posMiddle [ 1 ] = posExtLabel [ 1 ] ;
569607 // console.log(labels[i]);
570608 // console.log(`label/middle/extLabel: ${posLabel}/${posMiddle}/${posExtLabel}`);
571609
@@ -574,7 +612,7 @@ function renderPie(
574612 ( posMiddle [ 1 ] - posLabel [ 1 ] ) ** 2
575613 ) ;
576614
577- if ( labels [ i ] !== "" ) {
615+ if ( labels [ i ] !== "" && ! labelHidden ) {
578616 // shift posLabel, toward the middle point
579617 posLabel [ 0 ] =
580618 posLabel [ 0 ] +
@@ -584,8 +622,7 @@ function renderPie(
584622 ( ( posMiddle [ 1 ] - posLabel [ 1 ] ) * labelWidth ) / distMiddleToLabel ;
585623
586624 // shift posExtLabel
587- posExtLabel [ 0 ] =
588- ( radius * 0.99 - extLabelWidth - 3 ) *
625+ posExtLabel [ 0 ] = posExtLabel [ 0 ] + ( - 3 ) *
589626 ( midAngle < Math . PI ? 1 : - 1 ) ; // multiply by 1 or -1 to put it on the right or on the left
590627 }
591628
0 commit comments