Lightweight plugin to render simple, animated and retina optimized pie charts
- highly customizable, no dependencies
- resolution independent (retina optimized)
- written in TypeScript, ships its own types
- ESM + UMD builds, ~2 kB gzipped
- optional jQuery plugin entry point
npm install easy-pie-chartimport { EasyPieChart } from 'easy-pie-chart';
const chart = new EasyPieChart(document.querySelector('.chart'), {
barColor: '#ef1e25',
size: 110,
});
chart.update(65);Via a script tag — the UMD bundle exposes a global EasyPieChart:
<script src="node_modules/easy-pie-chart/dist/easypiechart.min.js"></script>
<script>
new EasyPieChart(document.querySelector('.chart'), { size: 110 }).update(65);
</script><script src="jquery.js"></script>
<script src="node_modules/easy-pie-chart/dist/jquery.easypiechart.min.js"></script>
<script>
$('.chart').easyPieChart({ barColor: '#10b981' });
// the instance lives on the element's data
$('.chart').data('easyPieChart').update(42);
// tear it down
$('.chart').easyPieChart('destroy');
</script>As a module, when jQuery is not a global:
import { registerJQueryPlugin } from 'easy-pie-chart/jquery';
import $ from 'jquery';
registerJQueryPlugin($);2.x shipped dist/angular.easypiechart.js. It is not part of 3.x, because
AngularJS 1.x has been end-of-life since January 2022 and this package will not
advertise support for an unpatched framework.
The core is framework-agnostic, so the directive is a few lines in your own
code. This is a drop-in replacement for the 2.x one — same easypiechart
module name, same percent and options bindings, same restrict: 'AE':
angular.module('easypiechart', []).directive('easypiechart', () => ({
restrict: 'AE',
scope: { percent: '=', options: '=' },
link(scope, element) {
const chart = new EasyPieChart(element[0], scope.options || {});
scope.$watch('percent', (value) => chart.update(value || 0));
// optional: rebuild when the options object is replaced
scope.$watch('options', (o) => o && chart.setOptions(o), true);
// 2.x had no teardown, so charts leaked whenever a scope was destroyed
scope.$on('$destroy', () => chart.destroy());
},
}));Markup is unchanged from 2.x:
<div easypiechart percent="model.percent" options="model.options"></div>Load the UMD bundle before your app so EasyPieChart is a global, or import
it if you bundle. If you would rather not migrate at all, 2.1.7 stays on npm
indefinitely — easy-pie-chart@2.1.7/dist/angular.easypiechart.js resolves on
unpkg and jsDelivr as it always has.
Every option except the callbacks can be set on the element. Attributes win over the options object, so you can share defaults in JS and override them per element — the same ordering the 2.x jQuery plugin used:
$('.chart').easyPieChart({ barColor: '#ef1e25' }); // default for all
// <div class="chart" data-bar-color="#10b981"></div> <- this one is green<div class="chart" data-percent="65" data-size="140" data-bar-color="#7c3aed"></div>data-track-color="false" and data-scale-color="false" disable the track and
the scale. data-percent sets the initial value.
| Option | Default | Description |
|---|---|---|
barColor |
'#ef1e25' |
CSS color string, gradient/pattern, or (value) => style |
trackColor |
'#f9f9f9' |
Track color, or false to disable |
trackBorderColor |
false |
Hairline along both edges of the track, or false |
trackBorderWidth |
1 |
Width of that hairline in px |
fillColor |
false |
Fill color for the disc inside the ring, or false |
scaleColor |
'#dfe0e0' |
Scale line color, or false to disable |
scaleLength |
5 |
Length of the scale lines in px (reduces the radius) |
scaleCount |
24 |
Number of scale lines |
lineCap |
'round' |
'butt', 'round' or 'square' |
lineWidth |
3 |
Width of the bar in px |
trackWidth |
lineWidth |
Width of the track in px |
size |
110 |
Size of the chart in px (always square) |
rotate |
0 |
Rotation of the whole chart in degrees |
arcLength |
360 |
How much of the circle the chart spans, in degrees |
max |
100 |
The value that corresponds to a full bar |
responsive |
false |
Resize the chart when the host element resizes |
canvasClass |
'easy-pie-chart-canvas' |
Class applied to the generated canvas |
animate |
{ duration: 1000, enabled: true } |
Also accepts a number (duration) or false. duration may be a (from, to) => ms function |
easing |
quadratic ease-in-out | (t, b, c, d) => number |
onStart |
— | (from, to) => void |
onStep |
— | (from, to, currentValue) => void |
onStop |
— | (from, to) => void |
renderer |
CanvasRenderer |
Custom renderer implementing IRenderer |
Values may be negative — the bar is then drawn counter-clockwise.
Set max to the value that should fill the bar. Callbacks and barColor still
receive your raw value, so labels need no conversion:
new EasyPieChart(el, {
max: 250,
onStep(from, to, value) {
this.el.querySelector('.label').textContent = `${Math.round(value)} / 250`;
},
}).update(125); // half a ringarcLength limits the sweep; combine it with rotate to place the opening.
A semi-circular gauge is 180 degrees rotated a quarter turn back:
new EasyPieChart(el, { arcLength: 180, rotate: -90, lineWidth: 10 });With responsive: true the chart follows the host element's size via
ResizeObserver. The host must take its size from CSS or its parent — if it
is sized by its content, it and the canvas would size each other:
.chart { width: 100%; aspect-ratio: 1; }new EasyPieChart(document.querySelector('.chart'), { responsive: true });Function options (barColor, easing, onStart, onStep, onStop) are bound
to the chart instance, so this.el inside them is the host element. Arrow
functions keep their own this, as usual.
barColor receives the current value and returns any valid canvas stroke
style — including a gradient built from the renderer's own context:
const chart = new EasyPieChart(el, {
barColor() {
const ctx = this.renderer.getCtx();
const { size } = this.options;
const gradient = ctx.createLinearGradient(0, 0, size, 0);
gradient.addColorStop(0, '#22c55e');
gradient.addColorStop(1, '#0ea5e9');
return gradient;
},
});The canvas is translated so 0,0 is its centre and rotated so 0% starts at 12
o'clock — take that into account when positioning gradient stops. Use
this.renderer.getCanvas() if you need the element itself.
| Method | Description |
|---|---|
update(value) |
Animate (or jump) to a new value. Non-numeric values are ignored. |
setOptions(options) |
Apply new options and redraw at the current value. |
stop() |
Stop a running animation at the current frame. |
enableAnimation() / disableAnimation() |
Toggle animated updates. |
destroy() |
Cancel animations and remove the canvas. |
value |
Getter for the current value. |
options |
The resolved options object. |
renderer |
The active renderer. getCtx() / getCanvas() on the canvas renderer. |
el |
The host element. |
All methods except destroy() and value return the instance for chaining.
Run npm run build, then open examples/index.html in a browser.
- Distributed as ESM (
dist/easypiechart.mjs), CommonJS (dist/easypiechart.cjs) and a minified UMD bundle for script tags (dist/easypiechart.min.js). The UMD global is stillEasyPieChart. TypeScript types are correct undernode16,nodenextandbundlerresolution. - The AngularJS 1.x directive was removed — AngularJS has been end-of-life
since January 2022. See AngularJS — migrating from 2.x
for a drop-in replacement directive, or stay on
2.1.7. - Bower and Meteor packaging were removed. Install from npm.
- The
easingsignature is now(t, b, c, d). The 2.x form(chart, t, b, c, d)and jQuery easing names are both still accepted, so existing configs keep working. - A 0% bar no longer renders a dot when
lineCapis'round'. update()ignoresNaNinstead of leaving the chart stuck.- New:
setOptions(),stop(),destroy(),scaleCount,data-*options on the vanilla constructor, and TypeScript types.
MIT