Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ export default () => (
<td>top</td>
<td>the gap position, value: top, bottom, left, right. </td>
</tr>
<tr>
<td>dot</td>
<td>Boolean | Object</td>
<td>false</td>
<td>within dot or not, value: true, false, { size: Number }</td>
</tr>
</tbody>
</table>

Expand Down
3 changes: 3 additions & 0 deletions docs/examples/gap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Example extends React.Component<ProgressProps, any> {
const circleContainerStyle = {
width: '200px',
height: '200px',
marginBottom: '60px'
};
const { percent, colorIndex } = this.state;
const color = getColor(colorIndex);
Expand All @@ -48,6 +49,7 @@ class Example extends React.Component<ProgressProps, any> {
strokeWidth={6}
strokeLinecap="square"
strokeColor={color}
dot={{ size: 10 }}
/>
</div>
<div style={circleContainerStyle}>
Expand All @@ -59,6 +61,7 @@ class Example extends React.Component<ProgressProps, any> {
trailWidth={6}
strokeLinecap="round"
strokeColor={[color, getColor(colorIndex + 1), getColor(colorIndex + 2)]}
dot={true}
/>
</div>

Expand Down
2 changes: 2 additions & 0 deletions docs/examples/gradient-circle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const Example = () => {
'0%': '#108ee9',
'100%': '#87d068',
}}
dot={true}
/>
</div>
<h3>Circle Progress {100}%</h3>
Expand Down Expand Up @@ -47,6 +48,7 @@ const Example = () => {
'0%': '#87d068',
},
]}
dot={{}}
/>
</div>
</div>
Expand Down
84 changes: 60 additions & 24 deletions src/Circle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import type { ProgressProps, GapPositionType } from './interface';

let gradientSeed = 0;

function pxToNumber(px: string) {
return parseInt(px.slice(0, px.indexOf('p')), 10);
}

function stripPercentToNumber(percent: string) {
return +percent.replace('%', '');
}
Expand Down Expand Up @@ -76,6 +80,7 @@ const Circle: React.FC<ProgressProps> = ({
className,
strokeColor,
percent,
dot,
...restProps
}) => {
const gradientId = React.useMemo(() => {
Expand All @@ -98,31 +103,62 @@ const Circle: React.FC<ProgressProps> = ({

const [paths] = useTransitionDuration(percentList);

const getDotList = (pathDoms) => {
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
if (dot) {
return pathDoms.map((pathDom, index) => {
const strokeDasharrayTemp = pathDom.props.style.strokeDasharray;
const strokeLength =
pxToNumber(strokeDasharrayTemp.slice(0, strokeDasharrayTemp.indexOf(' '))) +
Math.abs(pxToNumber(pathDom.props.style.strokeDashoffset)) +
strokeWidth / 2;

path.setAttribute('d', pathDom.props.d);
const dotPoint = path.getPointAtLength(strokeLength);
return (
<circle
key={index + 10}
className={`${prefixCls}-circle-dot`}
cx={dotPoint.x}
cy={dotPoint.y}
r={typeof dot === 'object' ? dot.size : strokeWidth}
fill={pathDom.props.stroke ? pathDom.props.stroke : pathDom.props.style.stroke}
/>
);
});
}
return [];

};

const getStokeList = () => {
let stackPtg = 0;
return percentList.map((ptg, index) => {
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
const stroke =
Object.prototype.toString.call(color) === '[object Object]'
? `url(#${prefixCls}-gradient-${gradientId})`
: '';
const pathStyles = getPathStyles(stackPtg, ptg, color, strokeWidth, gapDegree, gapPosition);
stackPtg += ptg;
return (
<path
key={index}
className={`${prefixCls}-circle-path`}
d={pathStyles.pathString}
stroke={stroke}
strokeLinecap={strokeLinecap}
strokeWidth={strokeWidth}
opacity={ptg === 0 ? 0 : 1}
fillOpacity="0"
style={pathStyles.pathStyle}
ref={paths[index]}
/>
);
});
const pathDoms = percentList
.map((ptg, index) => {
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
const stroke =
Object.prototype.toString.call(color) === '[object Object]'
? `url(#${prefixCls}-gradient-${gradientId})`
: '';
const pathStyles = getPathStyles(stackPtg, ptg, color, strokeWidth, gapDegree, gapPosition);
stackPtg += ptg;
return (
<path
key={index}
className={`${prefixCls}-circle-path`}
d={pathStyles.pathString}
stroke={stroke}
strokeLinecap={strokeLinecap}
strokeWidth={strokeWidth}
opacity={ptg === 0 ? 0 : 1}
fillOpacity="0"
style={pathStyles.pathStyle}
ref={paths[index]}
/>
);
})
.reverse();
return pathDoms.concat(getDotList(pathDoms));
};

return (
Expand Down Expand Up @@ -158,7 +194,7 @@ const Circle: React.FC<ProgressProps> = ({
fillOpacity="0"
style={pathStyle}
/>
{getStokeList().reverse()}
{getStokeList()}
</svg>
);
};
Expand Down
6 changes: 3 additions & 3 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRef, useEffect } from 'react';
import { ProgressProps } from './interface';
import type { ProgressProps } from './interface';

export const defaultProps: Partial<ProgressProps> = {
className: '',
Expand All @@ -8,7 +8,7 @@ export const defaultProps: Partial<ProgressProps> = {
strokeColor: '#2db7f5',
strokeLinecap: 'round',
strokeWidth: 1,
style: {},
style: { overflow: 'visible' },
trailColor: '#D9D9D9',
trailWidth: 1,
};
Expand All @@ -21,7 +21,7 @@ export const useTransitionDuration = (percentList: number[]) => {
const now = Date.now();
let updated = false;

Object.keys(paths).forEach(key => {
Object.keys(paths).forEach((key) => {
const path = paths[key].current;
if (!path) {
return;
Expand Down
5 changes: 4 additions & 1 deletion src/interface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import type * as React from 'react';

export interface ProgressProps {
strokeWidth?: number;
Expand All @@ -13,10 +13,13 @@ export interface ProgressProps {
gapDegree?: number;
gapPosition?: GapPositionType;
transition?: string;
dot?: dotType;
}

export type StrokeColorType = string | string[] | object;

export type GapPositionType = 'top' | 'right' | 'bottom' | 'left';

export type StrokeLinecapType = 'round' | 'butt' | 'square';

export type dotType = boolean | object;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export type dotType = boolean | object;
export type DotType = boolean | object;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object .size等的类型明确出来