vizon-countdown-website/src/ProgressCircle.jsx

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;