@@ -4,7 +4,7 @@ import { ChartContainer } from '@ui5/webcomponents-react-charts/lib/components/C
4
4
import { PieChartPlaceholder } from '@ui5/webcomponents-react-charts/lib/PieChartPlaceholder' ;
5
5
import { useLegendItemClick } from '@ui5/webcomponents-react-charts/lib/useLegendItemClick' ;
6
6
import 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' ;
8
8
import { getValueByDataKey } from 'recharts/lib/util/ChartUtils' ;
9
9
import { IChartBaseProps } from '../../interfaces/IChartBaseProps' ;
10
10
import { IChartMeasure } from '../../interfaces/IChartMeasure' ;
@@ -85,6 +85,8 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
85
85
} ;
86
86
} , [ props . chartConfig ] ) ;
87
87
88
+ const showActiveSegmentDataLabel = chartConfig . showActiveSegmentDataLabel ?? true ;
89
+
88
90
const dimension : DimensionConfig = useMemo (
89
91
( ) => ( {
90
92
formatter : defaultFormatter ,
@@ -103,7 +105,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
103
105
104
106
const dataLabel = useCallback (
105
107
( props ) => {
106
- if ( measure . hideDataLabel ) return null ;
108
+ if ( measure . hideDataLabel || chartConfig . activeSegment === props . index ) return null ;
107
109
108
110
if ( isValidElement ( measure . DataLabel ) ) {
109
111
return cloneElement ( measure . DataLabel , { ...props , config : measure } ) ;
@@ -115,7 +117,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
115
117
</ Text >
116
118
) ;
117
119
} ,
118
- [ measure ]
120
+ [ measure , chartConfig . activeSegment ]
119
121
) ;
120
122
121
123
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
143
145
[ onDataPointClick ]
144
146
) ;
145
147
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
+
146
227
return (
147
228
< ChartContainer
148
229
dataset = { dataset }
@@ -172,8 +253,10 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
172
253
data = { dataset }
173
254
animationBegin = { 0 }
174
255
isAnimationActive = { noAnimation === false }
175
- labelLine = { measure . hideDataLabel !== true }
256
+ labelLine = { renderLabelLine }
176
257
label = { dataLabel }
258
+ activeIndex = { chartConfig . activeSegment }
259
+ activeShape = { chartConfig . activeSegment != null && renderActiveShape }
177
260
>
178
261
{ centerLabel && < Label position = { 'center' } > { centerLabel } </ Label > }
179
262
{ dataset &&
@@ -199,6 +282,7 @@ const PieChart: FC<PieChartProps> = forwardRef((props: PieChartProps, ref: Ref<H
199
282
verticalAlign = { chartConfig . legendPosition }
200
283
align = { chartConfig . legendHorizontalAlign }
201
284
onClick = { onItemLegendClick }
285
+ wrapperStyle = { legendWrapperStyle }
202
286
/>
203
287
) }
204
288
</ PieChartLib >
0 commit comments