1
1
import * as React from 'react' ;
2
2
import classNames from 'classnames' ;
3
- import { useTransitionDuration , defaultProps } from './common' ;
3
+ import { defaultProps , useTransitionDuration } from './common' ;
4
4
import type { ProgressProps } from './interface' ;
5
5
import useId from './hooks/useId' ;
6
6
@@ -16,20 +16,19 @@ function toArray<T>(value: T | T[]): T[] {
16
16
const VIEW_BOX_SIZE = 100 ;
17
17
18
18
const getCircleStyle = (
19
- radius : number ,
19
+ perimeter : number ,
20
+ perimeterWithoutGap : number ,
20
21
offset : number ,
21
22
percent : number ,
23
+ rotateDeg : number ,
24
+ gapDegree ,
25
+ gapPosition : ProgressProps [ 'gapPosition' ] | undefined ,
22
26
strokeColor : string | Record < string , string > ,
23
- gapDegree = 0 ,
24
- gapPosition : ProgressProps [ 'gapPosition' ] ,
25
27
strokeLinecap : ProgressProps [ 'strokeLinecap' ] ,
26
28
strokeWidth ,
29
+ stepSpace = 0 ,
27
30
) => {
28
- const rotateDeg = gapDegree > 0 ? 90 + gapDegree / 2 : - 90 ;
29
- const perimeter = Math . PI * 2 * radius ;
30
- const perimeterWithoutGap = perimeter * ( ( 360 - gapDegree ) / 360 ) ;
31
31
const offsetDeg = ( offset / 100 ) * 360 * ( ( 360 - gapDegree ) / 360 ) ;
32
-
33
32
const positionDeg =
34
33
gapDegree === 0
35
34
? 0
@@ -45,7 +44,7 @@ const getCircleStyle = (
45
44
// https://github.com/ant-design/ant-design/issues/35009
46
45
if ( strokeLinecap === 'round' && percent !== 100 ) {
47
46
strokeDashoffset += strokeWidth / 2 ;
48
- // when percent is small enough (<= 1%), keep smallest value to avoid it's disapperance
47
+ // when percent is small enough (<= 1%), keep smallest value to avoid it's disappearance
49
48
if ( strokeDashoffset >= perimeterWithoutGap ) {
50
49
strokeDashoffset = perimeterWithoutGap - 0.01 ;
51
50
}
@@ -54,7 +53,7 @@ const getCircleStyle = (
54
53
return {
55
54
stroke : typeof strokeColor === 'string' ? strokeColor : undefined ,
56
55
strokeDasharray : `${ perimeterWithoutGap } px ${ perimeter } ` ,
57
- strokeDashoffset,
56
+ strokeDashoffset : strokeDashoffset + stepSpace ,
58
57
transform : `rotate(${ rotateDeg + offsetDeg + positionDeg } deg)` ,
59
58
transformOrigin : '50% 50%' ,
60
59
transition :
@@ -66,9 +65,10 @@ const getCircleStyle = (
66
65
const Circle : React . FC < ProgressProps > = ( {
67
66
id,
68
67
prefixCls,
68
+ steps,
69
69
strokeWidth,
70
70
trailWidth,
71
- gapDegree,
71
+ gapDegree = 0 ,
72
72
gapPosition,
73
73
trailColor,
74
74
strokeLinecap,
@@ -81,14 +81,21 @@ const Circle: React.FC<ProgressProps> = ({
81
81
const mergedId = useId ( id ) ;
82
82
const gradientId = `${ mergedId } -gradient` ;
83
83
const radius = VIEW_BOX_SIZE / 2 - strokeWidth / 2 ;
84
+ const perimeter = Math . PI * 2 * radius ;
85
+ const rotateDeg = gapDegree > 0 ? 90 + gapDegree / 2 : - 90 ;
86
+ const perimeterWithoutGap = perimeter * ( ( 360 - gapDegree ) / 360 ) ;
87
+ const { count : stepCount , space : stepSpace } =
88
+ typeof steps === 'object' ? steps : { count : steps , space : 2 } ;
84
89
85
90
const circleStyle = getCircleStyle (
86
- radius ,
91
+ perimeter ,
92
+ perimeterWithoutGap ,
87
93
0 ,
88
94
100 ,
89
- trailColor ,
95
+ rotateDeg ,
90
96
gapDegree ,
91
97
gapPosition ,
98
+ trailColor ,
92
99
strokeLinecap ,
93
100
strokeWidth ,
94
101
) ;
@@ -105,12 +112,14 @@ const Circle: React.FC<ProgressProps> = ({
105
112
const color = strokeColorList [ index ] || strokeColorList [ strokeColorList . length - 1 ] ;
106
113
const stroke = color && typeof color === 'object' ? `url(#${ gradientId } )` : undefined ;
107
114
const circleStyleForStack = getCircleStyle (
108
- radius ,
115
+ perimeter ,
116
+ perimeterWithoutGap ,
109
117
stackPtg ,
110
118
ptg ,
111
- color ,
119
+ rotateDeg ,
112
120
gapDegree ,
113
121
gapPosition ,
122
+ color ,
114
123
strokeLinecap ,
115
124
strokeWidth ,
116
125
) ;
@@ -132,7 +141,7 @@ const Circle: React.FC<ProgressProps> = ({
132
141
// React will call the ref callback with the DOM element when the component mounts,
133
142
// and call it with `null` when it unmounts.
134
143
// Refs are guaranteed to be up-to-date before componentDidMount or componentDidUpdate fires.
135
-
144
+
136
145
paths [ index ] = elem ;
137
146
} }
138
147
/>
@@ -141,6 +150,52 @@ const Circle: React.FC<ProgressProps> = ({
141
150
. reverse ( ) ;
142
151
} ;
143
152
153
+ const getStepStokeList = ( ) => {
154
+ // only show the first percent when pass steps
155
+ const current = Math . round ( stepCount * ( percentList [ 0 ] / 100 ) ) ;
156
+ const stepPtg = 100 / stepCount ;
157
+
158
+ let stackPtg = 0 ;
159
+ return new Array ( stepCount ) . fill ( null ) . map ( ( _ , index ) => {
160
+ const color = index <= current - 1 ? strokeColorList [ 0 ] : trailColor ;
161
+ const stroke = color && typeof color === 'object' ? `url(#${ gradientId } )` : undefined ;
162
+ const circleStyleForStack = getCircleStyle (
163
+ perimeter ,
164
+ perimeterWithoutGap ,
165
+ stackPtg ,
166
+ stepPtg ,
167
+ rotateDeg ,
168
+ gapDegree ,
169
+ gapPosition ,
170
+ color ,
171
+ 'butt' ,
172
+ strokeWidth ,
173
+ stepSpace ,
174
+ ) ;
175
+ stackPtg +=
176
+ ( ( perimeterWithoutGap - circleStyleForStack . strokeDashoffset + stepSpace ) * 100 ) /
177
+ perimeterWithoutGap ;
178
+
179
+ return (
180
+ < circle
181
+ key = { index }
182
+ className = { `${ prefixCls } -circle-path` }
183
+ r = { radius }
184
+ cx = { VIEW_BOX_SIZE / 2 }
185
+ cy = { VIEW_BOX_SIZE / 2 }
186
+ stroke = { stroke }
187
+ // strokeLinecap={strokeLinecap}
188
+ strokeWidth = { strokeWidth }
189
+ opacity = { 1 }
190
+ style = { circleStyleForStack }
191
+ ref = { ( elem ) => {
192
+ paths [ index ] = elem ;
193
+ } }
194
+ />
195
+ ) ;
196
+ } ) ;
197
+ } ;
198
+
144
199
return (
145
200
< svg
146
201
className = { classNames ( `${ prefixCls } -circle` , className ) }
@@ -160,17 +215,19 @@ const Circle: React.FC<ProgressProps> = ({
160
215
</ linearGradient >
161
216
</ defs >
162
217
) }
163
- < circle
164
- className = { `${ prefixCls } -circle-trail` }
165
- r = { radius }
166
- cx = { VIEW_BOX_SIZE / 2 }
167
- cy = { VIEW_BOX_SIZE / 2 }
168
- stroke = { trailColor }
169
- strokeLinecap = { strokeLinecap }
170
- strokeWidth = { trailWidth || strokeWidth }
171
- style = { circleStyle }
172
- />
173
- { getStokeList ( ) }
218
+ { ! stepCount && (
219
+ < circle
220
+ className = { `${ prefixCls } -circle-trail` }
221
+ r = { radius }
222
+ cx = { VIEW_BOX_SIZE / 2 }
223
+ cy = { VIEW_BOX_SIZE / 2 }
224
+ stroke = { trailColor }
225
+ strokeLinecap = { strokeLinecap }
226
+ strokeWidth = { trailWidth || strokeWidth }
227
+ style = { circleStyle }
228
+ />
229
+ ) }
230
+ { stepCount ? getStepStokeList ( ) : getStokeList ( ) }
174
231
</ svg >
175
232
) ;
176
233
} ;
0 commit comments