Skip to content

Instantly share code, notes, and snippets.

@Torthu
Last active February 16, 2021 09:33
Show Gist options
  • Save Torthu/bccd0291010ba94654dde450eaa35aa8 to your computer and use it in GitHub Desktop.
Save Torthu/bccd0291010ba94654dde450eaa35aa8 to your computer and use it in GitHub Desktop.
Circular Progress Bar in SVG/React without CSS
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