Last active
February 16, 2021 09:33
-
-
Save Torthu/bccd0291010ba94654dde450eaa35aa8 to your computer and use it in GitHub Desktop.
Circular Progress Bar in SVG/React without CSS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
interface CircleProgressProps { | |
progress: number; | |
diameter?: number; | |
strokeWidth?: number; | |
className?: string; | |
progressBackgroundColor?: string; | |
progressBarColor?: string; | |
rotation?: number; | |
} | |
export default function CircleProgress(props: CircleProgressProps) { | |
const { | |
diameter = 100, // Diameter of circle (including stroke) in px | |
className = "", | |
strokeWidth = 10, // Width of stroke in px | |
rotation = 270, // 270 degrees = start progress from top of circle | |
progressBackgroundColor = "#cccccc", // Frende Gray? | |
progressBarColor = "#468330" // Frende Green? | |
} = props; | |
// Make sure we always render something, even if progress is null/undefined/invalid number/NaN | |
let progress = props.progress ?? 0; | |
if (progress < 0 || isNaN(progress)) { | |
progress = 0; | |
} else if (progress > 100) { | |
progress = 100; | |
} | |
// Radius including stroke | |
const outerRadius = diameter / 2; | |
// Radius without stroke | |
const innerRadius = diameter / 2 - strokeWidth; | |
// Circumference of circle without stroke | |
const innerCircumference = 2 * Math.PI * innerRadius; | |
// Make the stroke as "wide" as the circle circumference | |
const strokeDasharray = innerCircumference; | |
// Offset = the amount of progressbar to show | |
const strokeDashoffset = ((100 - progress) / 100) * innerCircumference; | |
// Rotate circle with rotation center === the circle center | |
const rotationTransform = `rotate(${rotation} ${outerRadius} ${outerRadius})`; | |
return ( | |
<svg | |
className={className} | |
width={diameter} | |
height={diameter} | |
viewBox={`0 0 ${diameter} ${diameter}`} | |
version="1.1" | |
xmlns="http://www.w3.org/2000/svg" | |
> | |
<g width={diameter} height={diameter} transform={rotationTransform}> | |
<circle | |
className="ff-progressBackground" | |
r={innerRadius} | |
cx={outerRadius} | |
cy={outerRadius} | |
stroke={progressBackgroundColor} | |
strokeWidth={strokeWidth} | |
fill="transparent" | |
></circle> | |
<circle | |
className="ff-progressBar" | |
r={innerRadius} | |
cx={outerRadius} | |
cy={outerRadius} | |
stroke={progressBarColor} | |
strokeWidth={strokeWidth} | |
fill="transparent" | |
strokeDasharray={strokeDasharray} | |
strokeDashoffset={strokeDashoffset} | |
></circle> | |
</g> | |
</svg> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment