@tomickigrzegorz/circular-progress-bar
v1.5.0
Published
A circular progress bar in svg
Maintainers
Readme
Demo
See the demo - example
Installation
CDN (jsDelivr)
<script src="https://cdn.jsdelivr.net/gh/tomickigrzegorz/[email protected]/dist/circularProgressBar.min.js"></script>npm
npm install @tomickigrzegorz/circular-progress-bar
# or
yarn add @tomickigrzegorz/circular-progress-barESM (bundler / Vite / Webpack)
import CircularProgressBar from "@tomickigrzegorz/circular-progress-bar";No CSS import needed — all styles are applied programmatically via SVG attributes.
ESM via CDN (no bundler)
<script type="module">
import CircularProgressBar from "https://cdn.jsdelivr.net/npm/@tomickigrzegorz/circular-progress-bar/dist/circularProgressBar.esm.min.js";
</script>UMD (CommonJS / Node)
const CircularProgressBar = require("@tomickigrzegorz/circular-progress-bar");Local file
<script src="./path/to/circularProgressBar.min.js"></script>Sample configuration
- Add a div element to the page
<div class="pie" data-pie='{ "percent": 80 }'></div> - Build the script or download it from the
distfolder and addcircularProgressBar.min.jsto the page, [umd, esm, iife] - Call the functions
const circle = new CircularProgressBar('pie'); circle.initial();
More extensive example:
<div class="pie" data-pie='{ "round": true, "percent": 80, "colorSlice": "#E91E63", "time": 20 }'></div>
<div class="pie" data-pie='{ "lineargradient": ["#ffff00","#ff0000"], "percent": 20, "colorSlice": "#000", "colorCircle": "#e6e6e6", "strokeWidth": 15, "number": false }'></div>Arc gradient — colors follow the arc of the circle. gradient[0] sits at the progress start, gradient[100%] at the end of the visible arc, and the colors flow in the progress direction. Combines freely with rotation, cut, inverse, and round.
<!-- equal spacing -->
<div class="pie" data-pie='{ "percent": 75, "gradient": ["#ff0000","#ffff00","#00cc00"], "colorCircle": "#e6e6e6", "round": true }'></div>
<!-- custom stop positions -->
<div class="pie" data-pie='{ "percent": 75, "gradient": ["#ff0000","#ffff00","#00cc00"], "gradientStops": [0,20,100], "colorCircle": "#e6e6e6" }'></div>
<!-- hard cuts (no blending) — duplicate each color at the same position -->
<div class="pie" data-pie='{ "percent": 75, "gradient": ["#ff0000","#ff0000","#00cc00","#00cc00"], "gradientStops": [0,50,50,100] }'></div>
<!-- with cut + rotation + round -->
<div class="pie" data-pie='{ "percent": 75, "gradient": ["#e91e63","#9c27b0","#3f51b5"], "colorCircle": "#e6e6e6", "cut": 30, "rotation": 144, "round": true }'></div>
<!-- counter-clockwise growth with round caps -->
<div class="pie" data-pie='{ "percent": 75, "gradient": ["#ff0000","#ff8800","#ffff00","#00cc00","#0000ff"], "colorCircle": "#e6e6e6", "inverse": true, "round": true }'></div>Minimal configuration:
<div class="pie" data-pie='{ "percent": 80 }'></div>Function call
// 'pie' is class name div
const circle = new CircularProgressBar("pie");
circle.initial();IntersectionObserver
Automatic animation start when the progress bar appears in the page view.
window.addEventListener('DOMContentLoaded', () => {
// get all progress bar
const elements = [].slice.call(document.querySelectorAll('.pie'));
// call to function
const circle = new CircularProgressBar('pie');
// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
// if IntersectionObserver is supported by the browser
if ('IntersectionObserver' in window) {
const config = {
root: null,
rootMargin: '0px',
threshold: 0.75,
};
const ovserver = new IntersectionObserver((entries, observer) => {
entries.map((entry) => {
if (entry.isIntersecting && entry.intersectionRatio >= 0.75) {
circle.initial(entry.target);
observer.unobserve(entry.target);
}
});
}, config);
elements.map((item) => {
ovserver.observe(item);
});
} else {
// if the browser does not support IntersectionObserver
// we run all progress bars at once
elements.map((element) => {
circle.initial(element);
});
}
});Update progress bar dynamically
Below there are properties that we can change dynamically
const circle = new CircularProgressBar("pie");
circle.initial();
setTimeout(() => {
const options = {
// item number you want to update
// read data-pie-index from the element
index: 1,
// update props
percent: 30,
colorSlice: "salmon",
fontColor: "salmon",
fontSize: "1.2rem",
fontWeight: 600
};
circle.animationTo(options);
}, 3000); // after 3s updateModification of these elements fontColor, fontSize, fontWeight is also available from the level of css. The svg text and tspan elements have unique classes on the basis of which we can modify them.
<text class="pie-text-1" x="50%" y="50%" fill="#000" font-size="1.6rem" font-weight="400" text-anchor="middle" dy="0.35em">
<tspan class="pie-percent-1">75</tspan>
<tspan class="pie-unit-1">%</tspan>
</text>.pie-text-1 {
fill: red;
font-size: 2rem;
/* e.t.c */
}Global configuration
<div class="global" data-pie='{ "percent": 90 }'></div>
<div class="global" data-pie='{ "percent": 10 }'></div>
...const globalConfig = {
"strokeBottom": 5,
"colorSlice": "#EC407A",
"colorCircle": "#f1f1f1",
"round": true,
/* e.t.c */
}
const global = new CircularProgressBar('global', globalConfig);
global.initial();TypeScript
The library includes built-in TypeScript declarations — no @types/ package needed.
import CircularProgressBar, { type CPBOptions } from "@tomickigrzegorz/circular-progress-bar";
const options: CPBOptions = {
percent: 75,
colorSlice: "#E91E63",
round: true,
};
const circle = new CircularProgressBar("pie", options);
circle.initial();Watch/Build the app
Watch the app, just call:
yarn watch
# or
npm run watchBuild app:
yarn build
# or
npm run buildConfiguration of the plugin
| props | type | default | require | description |
| -------------- | :-----------: | :---------: | :-----: | ---------------------------------------------------------------------------------------------------------- |
| percent | number | | ✔ | Represents the progress bar and animation of the animation progress expressed by a number e.g. 65% |
| index | number | | | Set your number `data-pie-index`, if you do not set it, it will be dynamically set depending on the order of elements |
| colorSlice | string | `'#00a1ff'` | | Progress layer color and background ["#ffff00","brown" <sup>2</sup>](#colors-names) |
| colorCircle | string | `''` | | Bottom circle color Font ["#ffff00","brown" <sup>2</sup>](#colors-names) |
| speed | number | `1000` | | Frame rate animation [fps]. Let's say you want the animation to be 60fps, just add the parameter speed: 60 |
| stroke | number | `10` | | Stroke width, chart thickness |
| strokeBottom | number | `10` | | If "strokBottom" is set, it is used to generate a background circle size |
| round | boolean | `false` | | Path rounding |
| inverse | boolean | `false` | | Counterclockwise animation |
| rotation | number | `-90` | | Chart rotation |
| number | boolean | `true` | | Add props number and set to false to hide the number with percent |
| animationOff | boolean | `false` | | Turn off the progress animation |
| animationSmooth| string | `''` | | Animation type setting, e.g. `500ms ease-out` - [more on transition](https://developer.mozilla.org/en-US/docs/Web/CSS/transition) |
| size | number | `200` | | Size progress bar width and height in px |
| cut | number | `0` | | Angle of the circle sector |
| unit | string | `%` | | Different unit instead of percentage (%) inside the circle <sup>1</sup> |
| fill | string | `none` | | Inner circle color |
| textPosition | string | `0.35em` | | The position of the SVG TEXT element vertically |
| fontSize | string | `1.6rem` | | Font size. The font can be shown in units rem, em, px ... |
| fontWeight | string | `400` | | [number, normal, bold, bolder, lighter] |
| fontColor | string | `'#000'` | | Font color ["#ffff00","brown" <sup>2</sup>](#colors-names) |
| lineargradient | array | | | Array of colors "lineargradient": "#ffff00","brown" 2 |
| gradient | array | | | Arc gradient — colors follow the arc of the circle. Array of 2–10 hex strings e.g. `["#f00","#ff0","#0f0"]` |
| gradientStops | array | | | Color stop positions (0–100) for gradient. Must match gradient length, otherwise equal spacing is used |
| strokeDasharray| string | `` | | It works only on the lowest circle and only on whole circles - stroke-dasharray |
1 unit - you can style them. unit is in the tspan element of the class pie-unit-x. The class name is main class + unit + chart id. Below are the styles for our example.
.pie-unit-9 {
fill: #f50057;
font-size: 1rem;
}Adding a shadow
[data-pie-index='2'] {
position: relative;
border-radius: 50%;
box-shadow: inset 0 0 25px 10px rgb(162, 202, 255);
}Browser support
Supports all modern browsers (Chrome, Firefox, Safari, Edge). IE is not supported.
License
This project is available under the MIT license.
