@@ -4,7 +4,7 @@ import { ChartContainer } from '@ui5/webcomponents-react-charts/lib/components/C
44import { PieChartPlaceholder } from '@ui5/webcomponents-react-charts/lib/PieChartPlaceholder' ;
55import { useLegendItemClick } from '@ui5/webcomponents-react-charts/lib/useLegendItemClick' ;
66import React , { CSSProperties , FC , forwardRef , Ref , useCallback , useMemo , isValidElement , cloneElement } from 'react' ;
7- import { Cell , Label , Legend , Pie , PieChart as PieChartLib , Tooltip , Text } from 'recharts' ;
7+ import { Cell , Label , Legend , Pie , PieChart as PieChartLib , Tooltip , Text , Sector } from 'recharts' ;
88import { getValueByDataKey } from 'recharts/lib/util/ChartUtils' ;
99import { IChartBaseProps } from '../../interfaces/IChartBaseProps' ;
1010import { IChartMeasure } from '../../interfaces/IChartMeasure' ;
@@ -85,6 +85,8 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
8585 } ;
8686 } , [ props . chartConfig ] ) ;
8787
88+ const showActiveSegmentDataLabel = chartConfig . showActiveSegmentDataLabel ?? true ;
89+
8890 const dimension : DimensionConfig = useMemo (
8991 ( ) => ( {
9092 formatter : defaultFormatter ,
@@ -103,7 +105,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
103105
104106 const dataLabel = useCallback (
105107 ( props ) => {
106- if ( measure . hideDataLabel ) return null ;
108+ if ( measure . hideDataLabel || chartConfig . activeSegment === props . index ) return null ;
107109
108110 if ( isValidElement ( measure . DataLabel ) ) {
109111 return cloneElement ( measure . DataLabel , { ...props , config : measure } ) ;
@@ -115,7 +117,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
115117 </ Text >
116118 ) ;
117119 } ,
118- [ measure ]
120+ [ measure , chartConfig . activeSegment ]
119121 ) ;
120122
121123 const tooltipValueFormatter = useCallback ( ( value , name ) => [ measure . formatter ( value ) , dimension . formatter ( name ) ] , [
@@ -143,6 +145,85 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
143145 [ onDataPointClick ]
144146 ) ;
145147
148+ const renderActiveShape = useCallback (
149+ ( props ) => {
150+ const RADIAN = Math . PI / 180 ;
151+ const { cx, cy, midAngle, innerRadius, outerRadius, startAngle, endAngle, fill, payload, percent, value } = props ;
152+ const sin = Math . sin ( - RADIAN * midAngle ) ;
153+ const cos = Math . cos ( - RADIAN * midAngle ) ;
154+ const sx = cx + ( outerRadius + 10 ) * cos ;
155+ const sy = cy + ( outerRadius + 10 ) * sin ;
156+ const mx = cx + ( outerRadius + 30 ) * cos ;
157+ const my = cy + ( outerRadius + 30 ) * sin ;
158+ const ex = mx + ( cos >= 0 ? 1 : - 1 ) * 22 ;
159+ const ey = my ;
160+ const textAnchor = cos >= 0 ? 'start' : 'end' ;
161+
162+ return (
163+ < g >
164+ < text x = { cx } y = { cy } dy = { 8 } textAnchor = "middle" fill = { fill } >
165+ { payload . name }
166+ </ text >
167+ < Sector
168+ cx = { cx }
169+ cy = { cy }
170+ innerRadius = { innerRadius }
171+ outerRadius = { outerRadius }
172+ startAngle = { startAngle }
173+ endAngle = { endAngle }
174+ fill = { fill }
175+ />
176+ < Sector
177+ cx = { cx }
178+ cy = { cy }
179+ startAngle = { startAngle }
180+ endAngle = { endAngle }
181+ innerRadius = { outerRadius + 6 }
182+ outerRadius = { outerRadius + 10 }
183+ fill = { fill }
184+ />
185+ { showActiveSegmentDataLabel && (
186+ < >
187+ < path d = { `M${ sx } ,${ sy } L${ mx } ,${ my } L${ ex } ,${ ey } ` } stroke = { fill } fill = "none" />
188+ < circle cx = { ex } cy = { ey } r = { 2 } fill = { fill } stroke = "none" />
189+ < text x = { ex + ( cos >= 0 ? 1 : - 1 ) * 12 } y = { ey } textAnchor = { textAnchor } fill = { fill } >
190+ { measure . formatter ( value ) }
191+ </ text >
192+ < text x = { ex + ( cos >= 0 ? 1 : - 1 ) * 12 } y = { ey } dy = { 18 } textAnchor = { textAnchor } fill = { fill } >
193+ { `(${ ( percent * 100 ) . toFixed ( 2 ) } %)` }
194+ </ text >
195+ </ >
196+ ) }
197+ </ g >
198+ ) ;
199+ } ,
200+ [ showActiveSegmentDataLabel ]
201+ ) ;
202+
203+ const renderLabelLine = useCallback (
204+ ( props ) => {
205+ if ( ! measure . hideDataLabel || chartConfig . activeSegment === props . index ) return null ;
206+ return Pie . renderLabelLineItem ( undefined , props ) ;
207+ } ,
208+ [ chartConfig . activeSegment ]
209+ ) ;
210+
211+ const legendWrapperStyle = useMemo ( ( ) => {
212+ if ( chartConfig . activeSegment != null && showActiveSegmentDataLabel ) {
213+ if ( chartConfig . legendPosition === 'bottom' ) {
214+ return {
215+ paddingTop : '30px'
216+ } ;
217+ } else if ( chartConfig . legendPosition === 'top' ) {
218+ return {
219+ paddingBottom : '30px'
220+ } ;
221+ }
222+ }
223+
224+ return null ;
225+ } , [ showActiveSegmentDataLabel , chartConfig . activeSegment , chartConfig . legendPosition ] ) ;
226+
146227 return (
147228 < ChartContainer
148229 dataset = { dataset }
@@ -172,8 +253,10 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
172253 data = { dataset }
173254 animationBegin = { 0 }
174255 isAnimationActive = { noAnimation === false }
175- labelLine = { measure . hideDataLabel !== true }
256+ labelLine = { renderLabelLine }
176257 label = { dataLabel }
258+ activeIndex = { chartConfig . activeSegment }
259+ activeShape = { chartConfig . activeSegment != null && renderActiveShape }
177260 >
178261 { centerLabel && < Label position = { 'center' } > { centerLabel } </ Label > }
179262 { dataset &&
@@ -199,6 +282,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
199282 verticalAlign = { chartConfig . legendPosition }
200283 align = { chartConfig . legendHorizontalAlign }
201284 onClick = { onItemLegendClick }
285+ wrapperStyle = { legendWrapperStyle }
202286 />
203287 ) }
204288 </ PieChartLib >
0 commit comments