64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import clsx from 'clsx';
|
|
import React from 'react';
|
|
|
|
|
|
interface RadialProgressBarProps {
|
|
percentage: number;
|
|
text: string;
|
|
color: string;
|
|
spanClassName?: string;
|
|
size?: number;
|
|
strokeWidth?: number;
|
|
strokeOpacity?: number;
|
|
}
|
|
|
|
|
|
// https://gist.github.com/eYinka/873be69fae3ef27b103681b8a9f5e379 Omarmarei's answer
|
|
const RadialProgressBar: React.FC<RadialProgressBarProps> = ({
|
|
percentage,
|
|
text,
|
|
color,
|
|
spanClassName = "",
|
|
size = 100,
|
|
strokeWidth = 10,
|
|
strokeOpacity = 0.5
|
|
}) => {
|
|
const radius = (size - strokeWidth) / 2;
|
|
const circumference = 2 * Math.PI * radius;
|
|
const offset = circumference - (percentage / 100) * circumference;
|
|
return (
|
|
<div className='relative flex items-center justify-center' style={{ width: size, height: size}}>
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox={`0 0 ${size} ${size}`
|
|
}
|
|
className="circular-progress-bar"
|
|
>
|
|
<circle className="circle-bg" stroke="#e6e6e6" strokeWidth={strokeWidth}
|
|
fill="none"
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
strokeOpacity={strokeOpacity}
|
|
/>
|
|
<circle
|
|
className="circle-progress"
|
|
stroke={color}
|
|
strokeWidth={strokeWidth}
|
|
strokeLinecap="round"
|
|
fill="none"
|
|
cx={size / 2}
|
|
cy={size / 2}
|
|
r={radius}
|
|
strokeDasharray={circumference}
|
|
strokeDashoffset={offset}
|
|
transform={`rotate(-90 ${size / 2} ${size / 2})`}
|
|
strokeOpacity={strokeOpacity}
|
|
/>
|
|
</svg>
|
|
<span className={clsx('absolute', spanClassName)}>{text}</span>
|
|
</div>
|
|
);
|
|
};
|
|
export default RadialProgressBar; |