Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
35 changes: 21 additions & 14 deletions examples/gap.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Circle } from 'rc-progress';

const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A'];
function getColor(index) {
return colorMap[(index + colorMap.length) % colorMap.length];
}
class Example extends Component {
constructor() {
super();
this.state = {
percent: 30,
color: '#3FC7FA',
colorIndex: 0,
};
this.changeState = this.changeState.bind(this);
}

changeState() {
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A'];
const value = parseInt(Math.random() * 100, 10);
const colorIndex = parseInt(Math.random() * 3, 10);
this.setState({
percent: value,
color: colorMap[parseInt(Math.random() * 3, 10)],
colorIndex,
});
}

Expand All @@ -27,52 +31,55 @@ class Example extends Component {
width: '200px',
height: '200px',
};
const { percent, colorIndex } = this.state;
const color = getColor(colorIndex);
return (
<div>
<p>
<button onClick={this.changeState}>Change State [{percent}]</button>
</p>
<div style={circleContainerStyle}>
<Circle
percent={this.state.percent}
percent={percent}
gapDegree={70}
gapPosition="top"
strokeWidth="6"
strokeLinecap="square"
strokeColor={this.state.color}
strokeColor={color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.state.percent}
percent={[percent / 3, percent / 3, percent / 3]}
gapDegree={70}
gapPosition="bottom"
strokeWidth="6"
trailWidth="6"
strokeLinecap="round"
strokeColor={this.state.color}
strokeColor={[color, getColor(colorIndex + 1), getColor(colorIndex + 2)]}
/>
</div>

<div style={circleContainerStyle}>
<Circle
percent={this.state.percent}
percent={percent}
gapDegree={70}
gapPosition="left"
strokeWidth="6"
strokeLinecap="square"
strokeColor={this.state.color}
strokeColor={color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.state.percent}
percent={percent}
gapDegree={70}
gapPosition="right"
strokeWidth="6"
strokeLinecap="square"
strokeColor={this.state.color}
strokeColor={color}
/>
</div>
<p>
<button onClick={this.changeState}>Change State</button>
</p>
</div>
);
}
Expand Down
16 changes: 11 additions & 5 deletions examples/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Example extends Component {
}

render() {
const { percent, color } = this.state;
const containerStyle = {
width: '250px',
};
Expand All @@ -33,17 +34,22 @@ class Example extends Component {
};
return (
<div>
<h3>Line Progress {this.state.percent}%</h3>
<h3>Line Progress {percent}%</h3>
<div style={containerStyle}>
<Line percent={this.state.percent} strokeWidth="4" strokeColor={this.state.color} />
<Line percent={percent} strokeWidth="4" strokeColor={color} />
<Line
percent={[percent / 2, percent / 2]}
strokeWidth="4"
strokeColor={[color, '#CCC']}
/>
</div>
<h3>Circle Progress {this.state.percent}%</h3>
<h3>Circle Progress {percent}%</h3>
<div style={circleContainerStyle}>
<Circle
percent={this.state.percent}
percent={percent}
strokeWidth="6"
strokeLinecap="round"
strokeColor={this.state.color}
strokeColor={color}
/>
</div>
<p>
Expand Down
76 changes: 52 additions & 24 deletions src/Circle.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import enhancer from './enhancer';
import { propTypes, defaultProps } from './types';

class Circle extends Component {
getPathStyles() {
const { percent, strokeWidth, strokeColor, gapDegree = 0, gapPosition } = this.props;
getPathStyles(offset, percent, strokeColor, strokeWidth, gapDegree = 0, gapPosition) {
const radius = 50 - (strokeWidth / 2);
let beginPositionX = 0;
let beginPositionY = -radius;
Expand Down Expand Up @@ -35,29 +34,66 @@ class Circle extends Component {
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 = {

const pathStyle = {
stroke: strokeColor,
strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2}px`,
strokeDashoffset: `-${gapDegree / 2 + offset / 100 * (len - gapDegree)}px`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
};
return { pathString, trailPathStyle, strokePathStyle };

return {
pathString,
pathStyle,
};
}

getStokeList() {
const {
prefixCls, percent, strokeColor, strokeWidth, strokeLinecap,
gapDegree, gapPosition,
} = this.props;
const percentList = Array.isArray(percent) ? percent : [percent];
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];

let stackPtg = 0;
return percentList.map((ptg, index) => {
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
const { pathString, pathStyle } = this.getPathStyles(
stackPtg, ptg, color, strokeWidth, gapDegree, gapPosition
);

stackPtg += ptg;

return (
<path
key={index}
className={`${prefixCls}-circle-path`}
d={pathString}
strokeLinecap={strokeLinecap}
strokeWidth={ptg === 0 ? 0 : strokeWidth}
fillOpacity="0"
style={pathStyle}
ref={(path) => {
this.paths[index] = path;
}}
/>
);
});
}

paths = {};

render() {
const {
prefixCls, strokeWidth, trailWidth, percent,
prefixCls, strokeWidth, trailWidth,
gapDegree, gapPosition,
trailColor, strokeLinecap, style, className, ...restProps,
} = this.props;
const { pathString, trailPathStyle, strokePathStyle } = this.getPathStyles();
const { pathString, pathStyle } = this.getPathStyles(
0, 100, trailColor, strokeWidth, gapDegree, gapPosition
);
delete restProps.percent;
delete restProps.gapDegree;
delete restProps.gapPosition;
delete restProps.strokeColor;
return (
<svg
Expand All @@ -73,17 +109,9 @@ class Circle extends Component {
strokeLinecap={strokeLinecap}
strokeWidth={trailWidth || strokeWidth}
fillOpacity="0"
style={trailPathStyle}
/>
<path
className={`${prefixCls}-circle-path`}
d={pathString}
strokeLinecap={strokeLinecap}
strokeWidth={this.props.percent === 0 ? 0 : strokeWidth}
fillOpacity="0"
ref={(path) => { this.path = path; }}
style={strokePathStyle}
style={pathStyle}
/>
{this.getStokeList()}
</svg>
);
}
Expand Down
48 changes: 33 additions & 15 deletions src/Line.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import enhancer from './enhancer';
import { propTypes, defaultProps } from './types';

class Line extends Component {
paths = {};

render() {
const {
className,
Expand All @@ -19,11 +21,8 @@ class Line extends Component {

delete restProps.gapPosition;

const pathStyle = {
strokeDasharray: '100px, 100px',
strokeDashoffset: `${(100 - percent)}px`,
transition: 'stroke-dashoffset 0.3s ease 0s, stroke 0.3s linear',
};
const percentList = Array.isArray(percent) ? percent : [percent];
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];

const center = strokeWidth / 2;
const right = 100 - (strokeWidth / 2);
Expand All @@ -32,6 +31,8 @@ class Line extends Component {
L ${strokeLinecap === 'round' ? right : 100},${center}`;
const viewBoxString = `0 0 100 ${strokeWidth}`;

let stackPtg = 0;

return (
<svg
className={`${prefixCls}-line ${className}`}
Expand All @@ -48,16 +49,33 @@ class Line extends Component {
strokeWidth={trailWidth || strokeWidth}
fillOpacity="0"
/>
<path
className={`${prefixCls}-line-path`}
d={pathString}
strokeLinecap={strokeLinecap}
stroke={strokeColor}
strokeWidth={strokeWidth}
fillOpacity="0"
ref={(path) => { this.path = path; }}
style={pathStyle}
/>
{percentList.map((ptg, index) => {
const pathStyle = {
strokeDasharray: `${ptg}px, 100px`,
strokeDashoffset: `-${stackPtg}px`,
transition:
'stroke-dashoffset 0.3s ease 0s, stroke-dasharray .3s ease 0s, stroke 0.3s linear',
};
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];

stackPtg += ptg;

return (
<path
key={index}
className={`${prefixCls}-line-path`}
d={pathString}
strokeLinecap={strokeLinecap}
stroke={color}
strokeWidth={strokeWidth}
fillOpacity="0"
ref={(path) => {
this.paths[index] = path;
}}
style={pathStyle}
/>
);
})}
</svg>
);
}
Expand Down
28 changes: 20 additions & 8 deletions src/enhancer.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
const enhancer = WrappedComponent => class Progress extends WrappedComponent {
componentDidUpdate() {
if (!this.path) {
return;
}
const pathStyle = this.path.style;
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';
const now = Date.now();
if (this.prevTimeStamp && now - this.prevTimeStamp < 100) {
pathStyle.transitionDuration = '0s, 0s';
let updated = false;

Object.keys(this.paths).forEach((key) => {
const path = this.paths[key];

if (!path) {
return;
}

updated = true;
const pathStyle = path.style;
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s';

if (this.prevTimeStamp && now - this.prevTimeStamp < 100) {
pathStyle.transitionDuration = '0s, 0s';
}
});

if (updated) {
this.prevTimeStamp = Date.now();
}
this.prevTimeStamp = Date.now();
}

render() {
Expand Down
10 changes: 6 additions & 4 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ export const defaultProps = {
trailWidth: 1,
};

const mixedType = PropTypes.oneOfType([PropTypes.number, PropTypes.string]);

export const propTypes = {
className: PropTypes.string,
percent: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
percent: PropTypes.oneOfType([mixedType, PropTypes.arrayOf(mixedType)]),
prefixCls: PropTypes.string,
strokeColor: PropTypes.string,
strokeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
strokeLinecap: PropTypes.oneOf(['butt', 'round', 'square']),
strokeWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
strokeWidth: mixedType,
style: PropTypes.object,
trailColor: PropTypes.string,
trailWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
trailWidth: mixedType,
};