Skip to content

Commit 22ae75e

Browse files
authored
chore: merge conic logic, auto fallback (#254)
* chore: fallback of liner * chore: update direction * chore: update demo * chore: fallback of old bro
1 parent e23aaf1 commit 22ae75e

File tree

9 files changed

+115
-160
lines changed

9 files changed

+115
-160
lines changed

docs/examples/gap.tsx

-12
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,6 @@ class Example extends React.Component<ProgressProps, any> {
109109
gapDegree={70}
110110
strokeWidth={6}
111111
strokeColor={{
112-
'0%': 'red',
113-
'100%': 'blue',
114-
}}
115-
/>
116-
</div>
117-
<div style={circleContainerStyle}>
118-
<Circle
119-
percent={percent}
120-
gapDegree={70}
121-
strokeWidth={6}
122-
strokeColor={{
123-
conic: true,
124112
'0%': 'red',
125113
'99%': 'blue',
126114
'100%': 'green',

docs/examples/gradient-circle.tsx

+1-18
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,12 @@ const Example = () => {
3535
/>
3636
</div>
3737

38-
<h3>Circle With Success Percent {65}%</h3>
39-
<div style={circleContainerStyle}>
40-
<Circle
41-
percent={[65, 100]}
42-
strokeWidth={6}
43-
strokeLinecap="round"
44-
strokeColor={[
45-
'#87d068',
46-
{
47-
'100%': '#108ee9',
48-
'0%': '#87d068',
49-
},
50-
]}
51-
/>
52-
</div>
53-
5438
<h3>Circle colors</h3>
5539
<div style={circleContainerStyle}>
5640
<Circle
57-
percent={100}
41+
percent={90}
5842
strokeWidth={6}
5943
strokeColor={{
60-
conic: true,
6144
'0%': 'green',
6245
'99%': 'red',
6346
'100%': 'blue',

src/Circle/ColorGradient.tsx

-26
This file was deleted.

src/Circle/PtgCircle.tsx

+38-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
import * as React from 'react';
22
import type { ProgressProps } from '..';
3-
import type { StrokeColorType } from '../interface';
3+
import type { StrokeColorObject } from '../interface';
4+
5+
interface BlockProps {
6+
bg: string;
7+
children?: React.ReactNode;
8+
}
9+
10+
const Block = ({ bg, children }: BlockProps) => (
11+
<div
12+
style={{
13+
width: '100%',
14+
height: '100%',
15+
background: bg,
16+
}}
17+
>
18+
{children}
19+
</div>
20+
);
21+
22+
function getPtgColors(color: Record<string, string>, scale: number) {
23+
return Object.keys(color).map((key) => {
24+
const parsedKey = parseFloat(key);
25+
const ptgKey = `${Math.floor(parsedKey * scale)}%`;
26+
27+
return `${color[key]} ${ptgKey}`;
28+
});
29+
}
430

531
export interface ColorGradientProps {
632
prefixCls: string;
@@ -11,8 +37,7 @@ export interface ColorGradientProps {
1137
strokeLinecap: ProgressProps['strokeLinecap'];
1238
strokeWidth: ProgressProps['strokeWidth'];
1339
size: number;
14-
color: StrokeColorType;
15-
conic: boolean;
40+
color: string | StrokeColorObject;
1641
gapDegree: number;
1742
}
1843

@@ -27,19 +52,12 @@ const PtgCircle = React.forwardRef<SVGCircleElement, ColorGradientProps>((props,
2752
strokeLinecap,
2853
strokeWidth,
2954
size,
30-
conic,
3155
gapDegree,
3256
} = props;
3357

3458
const isGradient = color && typeof color === 'object';
3559

36-
const stroke = React.useMemo(() => {
37-
if (conic) {
38-
return '#FFF';
39-
}
40-
41-
return isGradient ? `url(#${gradientId})` : undefined;
42-
}, [gradientId, isGradient, conic]);
60+
const stroke = isGradient ? `#FFF` : undefined;
4361

4462
// ========================== Circle ==========================
4563
const halfSize = size / 2;
@@ -60,36 +78,30 @@ const PtgCircle = React.forwardRef<SVGCircleElement, ColorGradientProps>((props,
6078
);
6179

6280
// ========================== Render ==========================
63-
if (!conic) {
81+
if (!isGradient) {
6482
return circleNode;
6583
}
6684

6785
const maskId = `${gradientId}-conic`;
68-
const conicColorKeys = Object.keys(color).filter((key) => key !== 'conic');
6986

7087
const fromDeg = gapDegree ? `${180 + gapDegree / 2}deg` : '0deg';
7188

72-
const conicColors = conicColorKeys.map((key) => {
73-
const parsedKey = parseFloat(key);
74-
const ptgKey = `${gapDegree ? Math.floor((parsedKey * (360 - gapDegree)) / 360) : parsedKey}%`;
75-
76-
return `${color[key]} ${ptgKey}`;
77-
});
89+
const conicColors = getPtgColors(color, (360 - gapDegree) / 360);
90+
const linearColors = getPtgColors(color, 1);
7891

7992
const conicColorBg = `conic-gradient(from ${fromDeg}, ${conicColors.join(', ')})`;
93+
const linearColorBg = `linear-gradient(to ${gapDegree ? 'bottom' : 'top'}, ${linearColors.join(
94+
', ',
95+
)})`;
8096

8197
return (
8298
<>
8399
<mask id={maskId}>{circleNode}</mask>
84100

85101
<foreignObject x={0} y={0} width={size} height={size} mask={`url(#${maskId})`}>
86-
<div
87-
style={{
88-
width: '100%',
89-
height: '100%',
90-
background: conicColorBg,
91-
}}
92-
/>
102+
<Block bg={linearColorBg}>
103+
<Block bg={conicColorBg} />
104+
</Block>
93105
</foreignObject>
94106
</>
95107
);

src/Circle/index.tsx

+2-8
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import classNames from 'classnames';
33
import { defaultProps, useTransitionDuration } from '../common';
44
import type { ProgressProps } from '../interface';
55
import useId from '../hooks/useId';
6-
import ColorGradient from './ColorGradient';
76
import PtgCircle from './PtgCircle';
8-
import { VIEW_BOX_SIZE, getCircleStyle, isConicColor } from './util';
7+
import { VIEW_BOX_SIZE, getCircleStyle } from './util';
98

109
function toArray<T>(value: T | T[]): T[] {
1110
const mergedValue = value ?? [];
@@ -50,7 +49,7 @@ const Circle: React.FC<ProgressProps> = (props) => {
5049
string,
5150
string
5251
>;
53-
const isConicGradient = isConicColor(gradient);
52+
const isConicGradient = gradient && typeof gradient === 'object';
5453
const mergedStrokeLinecap = isConicGradient ? 'butt' : strokeLinecap;
5554

5655
const circleStyle = getCircleStyle(
@@ -98,7 +97,6 @@ const Circle: React.FC<ProgressProps> = (props) => {
9897
style={circleStyleForStack}
9998
strokeLinecap={mergedStrokeLinecap}
10099
strokeWidth={strokeWidth}
101-
conic={isConicGradient}
102100
gapDegree={gapDegree}
103101
ref={(elem) => {
104102
// https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
@@ -169,10 +167,6 @@ const Circle: React.FC<ProgressProps> = (props) => {
169167
role="presentation"
170168
{...restProps}
171169
>
172-
{/* Line Gradient */}
173-
{gradient && !isConicGradient && (
174-
<ColorGradient gradientId={gradientId} gradient={gradient} />
175-
)}
176170
{!stepCount && (
177171
<circle
178172
className={`${prefixCls}-circle-trail`}

src/Circle/util.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import type { StrokeColorObject, StrokeColorType } from '../interface';
1+
import type { StrokeColorType } from '../interface';
22
import type { ProgressProps } from '..';
33

44
export const VIEW_BOX_SIZE = 100;
55

6-
export function isConicColor(gradient: StrokeColorObject) {
7-
return gradient && gradient.conic;
8-
}
9-
106
export const getCircleStyle = (
117
perimeter: number,
128
perimeterWithoutGap: number,

src/interface.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ export interface ProgressProps {
1616
steps?: number | { count: number; space: number };
1717
}
1818

19-
export type StrokeColorObject = Partial<Record<`${number}%` | 'from' | 'to', string>> & {
20-
conic?: boolean;
21-
};
19+
export type StrokeColorObject = Record<string, string>;
2220

2321
export type BaseStrokeColorType = string | StrokeColorObject;
2422

tests/__snapshots__/conic.spec.tsx.snap

+10-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ exports[`Circle.conic gapDegree 1`] = `
4141
>
4242
<div
4343
style="width: 100%; height: 100%;"
44-
/>
44+
>
45+
<div
46+
style="width: 100%; height: 100%;"
47+
/>
48+
</div>
4549
</foreignobject>
4650
</svg>
4751
</DocumentFragment>
@@ -88,7 +92,11 @@ exports[`Circle.conic should work 1`] = `
8892
>
8993
<div
9094
style="width: 100%; height: 100%;"
91-
/>
95+
>
96+
<div
97+
style="width: 100%; height: 100%;"
98+
/>
99+
</div>
92100
</foreignobject>
93101
</svg>
94102
</DocumentFragment>

0 commit comments

Comments
 (0)