import * as React from 'react'; export interface ProgressCircleProps { className?: string, percent?: number, prefixCls?: string, strokeColor?: string, strokeLinecap?: 'butt' | 'round' | 'square', strokeWidth?: number, style?: React.CSSProperties, trailColor?: string, trailWidth?: number, gapPosition?: 'top' | 'bottom' | 'left' | 'right', gapDegree?: number, } export class ProgressCircle extends React.Component { static defaultProps: ProgressCircleProps = { className: '', percent: 0, prefixCls: 'rc-progress', strokeColor: '#2db7f5', strokeLinecap: 'round', strokeWidth: 1, style: {}, trailColor: '#D9D9D9', trailWidth: 1, gapPosition: "top", gapDegree: 0, } private prevTimeStamp: number; public path: SVGPathElement; constructor(props: ProgressCircleProps, context) { super(props, context); } componentDidUpdate() { const now = Date.now(); this.path.style.transitionDuration = '0.3s, 0.3s'; if (this.prevTimeStamp && now - this.prevTimeStamp < 100) { this.path.style.transitionDuration = '0s, 0s'; } this.prevTimeStamp = Date.now(); } private getPathStyles = () => { const { percent, strokeWidth, gapDegree = 0, gapPosition } = this.props; const radius = 50 - (strokeWidth / 2); let beginPositionX = 0; let beginPositionY = -radius; let endPositionX = 0; let endPositionY = -2 * radius; switch (gapPosition) { case 'left': beginPositionX = -radius; beginPositionY = 0; endPositionX = 2 * radius; endPositionY = 0; break; case 'right': beginPositionX = radius; beginPositionY = 0; endPositionX = -2 * radius; endPositionY = 0; break; case 'bottom': beginPositionY = radius; endPositionY = 2 * radius; break; default: } const pathString = `M 50,50 m ${beginPositionX},${beginPositionY} a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY} a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`; const len = Math.PI * 2 * radius; const trailPathStyle = { strokeDasharray: `${len - gapDegree}px ${len}px`, strokeDashoffset: `-${gapDegree / 2}px`, transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s', }; const strokePathStyle = { strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`, strokeDashoffset: `-${gapDegree / 2}px`, transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s', }; return { pathString, trailPathStyle, strokePathStyle }; } render() { const { prefixCls, strokeWidth, trailWidth, strokeColor, trailColor, strokeLinecap, style, className, percent, gapDegree, gapPosition, children, ...restProps } = this.props; const { pathString, trailPathStyle, strokePathStyle } = this.getPathStyles(); return ( { this.path = path; }} style={strokePathStyle} /> ); } }