Skip to content

Instantly share code, notes, and snippets.

@WJWang
Last active December 10, 2019 07:19
Show Gist options
  • Save WJWang/0033f9310f63a6877b61250fc9f99c3e to your computer and use it in GitHub Desktop.
Save WJWang/0033f9310f63a6877b61250fc9f99c3e to your computer and use it in GitHub Desktop.
ProgressRing in React Hooks
import React, { useState, useEffect } from 'react';
import T from 'prop-types';
import Ring from './components/Ring';
const targetProgress = 95;
function DemoErrorRing() {
const [progress, setProgress] = useState(0);
useEffect(() => {
const interval = setInterval(() => setProgress(progress + 1), 10);
return () => {
if (progress === targetProgress) {
clearInterval(interval);
}
};
});
return (
<Ring progress={progress} />
);
}
export default DemoErrorRing;
import React from 'react';
import T from 'prop-types';
function Ring({
radius, stroke, progress, strokeColor, strokeLinecap,
}) {
const innerRadius = radius - stroke * 2;
const circumference = innerRadius * 2 * Math.PI;
const strokeDashoffset = circumference - ((progress / 100) * circumference);
return (
<svg height={radius * 2} width={radius * 2}>
<circle
fill="transparent"
stroke={strokeColor}
strokeLinecap={strokeLinecap}
strokeWidth={stroke}
strokeDasharray={`${circumference} ${circumference}`}
style={{
strokeDashoffset,
transition: 'stroke-dashoffset 0.35s',
transform: 'rotate(90deg) scaleX(-1)',
transformOrigin: '50% 50%',
}}
r={innerRadius}
cx={radius}
cy={radius}
/>
</svg>
);
}
Ring.propTypes = {
radius: T.number,
stroke: T.number,
strokeColor: T.string,
strokeLinecap: T.string,
progress: T.number,
};
Ring.defaultProps = {
strokeLinecap: 'round',
strokeColor: '#572d88',
radius: 80,
stroke: 6,
progress: 20,
};
import React, { useState, useEffect, useRef } from 'react';
import Ring from './components/Ring';
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
function tick() {
savedCallback.current();
}
const id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
const targetProgress = 95;
function SuccessDemoRing() {
const step = 5;
const [progress, setProgress] = useState(0);
useInterval(() => {
if (progress !== targetProgress) {
if (progress + step > targetProgress) {
setProgress(targetProgress);
} else {
setProgress(progress + step);
}
}
}, 10);
return (
<Ring progress={progress} />
);
}
export default SuccessDemoRing;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment