114 lines
2.6 KiB
JavaScript
114 lines
2.6 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import style from './ProgressCircle.sass';
|
|
|
|
const ProgressCircle = ({
|
|
children,
|
|
min,
|
|
max,
|
|
progress,
|
|
size,
|
|
strokeWidth,
|
|
backStroke,
|
|
stroke,
|
|
}) => {
|
|
const width = size;
|
|
const height = size;
|
|
|
|
const extraWidth = width * 0.1;
|
|
const extraHeight = height * 0.1;
|
|
|
|
const viewBox = [
|
|
-extraWidth, -extraHeight,
|
|
width + (2 * extraWidth), height + (2 * extraHeight),
|
|
].join(' ');
|
|
|
|
const cx = width / 2;
|
|
const cy = height / 2;
|
|
|
|
const r = (size / 2) - (strokeWidth / 2);
|
|
|
|
const strokeLength = 2 * Math.PI * r;
|
|
|
|
const finalProgress = (progress - min) / (max - min);
|
|
|
|
const strokeDasharray = strokeLength;
|
|
const strokeDashoffset = strokeLength * (1 - finalProgress);
|
|
|
|
const dropShadowDefId = 'dropshadow';
|
|
|
|
return (
|
|
<div
|
|
className={style.progressCircleContainer}
|
|
style={{
|
|
width: `${width}px`,
|
|
height: `${height}px`,
|
|
}}
|
|
>
|
|
<svg
|
|
className={style.progressCircle}
|
|
style={{
|
|
margin: [
|
|
-extraHeight,
|
|
-extraWidth,
|
|
].join(' '),
|
|
}}
|
|
{...{ viewBox }}
|
|
>
|
|
<defs>
|
|
<filter
|
|
id={dropShadowDefId}
|
|
height={height + extraHeight}
|
|
width={width + extraWidth}
|
|
>
|
|
<feGaussianBlur in="SourceAlpha" stdDeviation="5" /> {/* stdDeviation is how much to blur */}
|
|
<feOffset dx="0" dy="0" result="offsetblur" /> {/* how much to offset */}
|
|
<feMerge>
|
|
<feMergeNode in="offsetBlur" />
|
|
<feMergeNode in="SourceGraphic" /> {/* this contains the element that the filter is applied to */}
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
<circle
|
|
fill="none"
|
|
stroke={backStroke}
|
|
filter={`url(#${dropShadowDefId})`}
|
|
{...{ cx, cy, r, strokeWidth }}
|
|
/>
|
|
<circle
|
|
className={style.progressValue}
|
|
fill="none"
|
|
{...{ cx, cy, r, stroke, strokeWidth, strokeDashoffset, strokeDasharray }}
|
|
/>
|
|
</svg>
|
|
<span className={style.progressCircleLabel}>
|
|
{children}
|
|
</span>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
ProgressCircle.propTypes = {
|
|
children: PropTypes.node,
|
|
size: PropTypes.number.isRequired,
|
|
progress: PropTypes.number,
|
|
strokeWidth: PropTypes.number,
|
|
min: PropTypes.number,
|
|
max: PropTypes.number,
|
|
backStroke: PropTypes.string,
|
|
stroke: PropTypes.string,
|
|
};
|
|
|
|
ProgressCircle.defaultProps = {
|
|
stroke: '#444',
|
|
backStroke: 'rgba(102, 166, 229, 0.12)',
|
|
strokeWidth: 10,
|
|
progress: 0.5,
|
|
min: 0,
|
|
max: 1,
|
|
children: null,
|
|
};
|
|
|
|
export default ProgressCircle;
|