React minimal pie chart
!Build Statusci-badgeci
!Npm versionnpm-version-badgenpm
!Coverallscoveralls-badgecoveralls
!Bundle sizebundlephobia-badgebundlephobiaLightweight React SVG pie charts, with versatile options and CSS animation included. < 2kB gzipped. π Demo πstorybook.
width="350px"
src="docs/chart.gif?raw=true"
alt="React minimal pie chart preview"
/>
Why?
Because Rechartsrecharts-github is awesome, but when you just need a simple pie/donought chart,| | Size
by Bundlefobia | Benchmark Size \* | Loading time
on a slow 3g \* | | :----------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | :---------------: | :-----------------------------: | | react-minimal-pie-chart (v8.4.0) | !Bundle size: React minimal pie chartbundlephobia-badgebundlephobia | 1.93 KB | ~39 ms | | rechartrecharts-github (v1.8.5) | !Bundle size: Rechartsrecharts-bundlephobia-badgerecharts-bundlephobia | 96.9 KB | ~1900 ms | | victory-pievictory-pie-github (v34.1.3) | !Bundle size: Victory pievictory-pie-bundlephobia-badgevictory-pie-bundlephobia | 50.5 KB | ~1100 ms | | react-apexchartsreact-apexcharts-github (v1.3.7) | !Bundle size: React apec chartsreact-apexcharts-bundlephobia-badgereact-apexcharts-bundlephobia | 114.6 KB | ~2300 ms | | react-visreact-vis-github (v1.11.7) | !Bundle size: React visreact-vis-bundlephobia-badgereact-vis-bundlephobia | 78.3 KB | ~1600 ms |
\ Benchmark carried out with size-limit with a "real-world" setup: see benchmark repo. (What matter here are not absolute values but the relation between magnitudes)
Features
- < 2kB gzipped
- Versatile: Pie, Donut, Loading, Completion charts (see Demostorybook)
- Customizable chart labels and CSS animations
- Written in Typescript
- No dependencies
Installation
npm install react-minimal-pie-chart
If you don't use a package manager,
react-minimal-pie-chart
exposes also an UMD
module ready for the browser.https://unpkg.com/react-minimal-pie-chart/dist/index.js
Minimum supported Typescript version: >=
3.8
Usage
import { PieChart } from 'react-minimal-pie-chart';
<PieChart
data={[
{ title: 'One', value: 10, color: '#E38627' },
{ title: 'Two', value: 15, color: '#C13C37' },
{ title: 'Three', value: 20, color: '#6A2135' },
]}
/>;
Options
| Property | Type | Description | Default | | --------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | datadata-props-docs |DataEntry[]
| Source data. Each entry represents a chart segment | |
| lineWidth | number
(%) | Line width of each segment. Percentage of chart's radius | 100 |
| startAngle | number
| Start angle of first segment | 0 |
| lengthAngle | number
| Total angle taken by the chart (can be negative to make the chart clockwise!) | 360 |
| totalValue | number
| Total value represented by the full chart | - |
| paddingAngle | number
| Angle between two segments | - |
| rounded | boolean
| Round line caps of each segment | - |
| segmentsShift | number
or:
(segmentIndex) => number
| Translates segments radially. If number
set, provide shift value relative to viewBoxSize
space. If function
, return a value for each segment.(
radius
prop might be adjusted to prevent segments from overflowing chart's boundaries) | - |
| segmentsStyle | CSSObject
or:
(segmentIndex) => CSSObject
| Style object assigned to each segment. If function
, return a value for each segment. (Warning: SVG only supports its own CSS propssvg-css). | - |
| segmentsTabIndex | number
| tabindex
attribute assigned to segments | - |
| labellabel-props-docs | (labelRenderProps) => string \| number \| ReactElement
| A function returning a label value or the SVG elementsvg-elements to be rendered as label | - |
| labelPosition | number
(%) | Label position from origin. Percentage of chart's radius (50 === middle point) | 50 |
| labelStyle | CSSObject
or:
(segmentIndex) => CSSObject
| Style object assigned to each label. If function
set, return style for each label. (Warning: SVG only supports its own CSS propssvg-css). | - |
| animate | boolean
| Animate segments on component mount | - |
| animationDuration | number
| Animation duration in ms | 500 |
| animationEasing | string
| A CSS easing function | ease-out |
| reveal | number
(%) | Turn on CSS animation and reveal just a percentage of each segment | - |
| background | string
| Segments' background color | - |
| children | ReactElement
(svg) | Elements rendered as children of SVG elementsvg-elements (eg. SVG defs
and gradient elements) | - |
| radius | number
(user units) | Radius of the pie (relative to viewBoxSize
space) | 50 |
| center | [number, number]
| x and y coordinates of center (relative to viewBoxSize
space) | 50, 50 |
| viewBoxSize | [number, number]
| width
and height
of SVG viewBox
attribute | 100, 100 |
| onBlur | (e, segmentIndex) => void
| onBlur
event handler for each segment | - |
| onClick | (e, segmentIndex) => void
| onClick
event handler for each segment | - |
| onFocus | (e, segmentIndex) => void
| onFocus
event handler for each segment | - |
| onKeyDown | (e, segmentIndex) => void
| onKeyDown
event handler for each segment | - |
| onMouseOut | (e, segmentIndex) => void
| onMouseOut
event handler for each segment | - |
| onMouseOver | (e, segmentIndex) => void
| onMouseOver
event handler for each segment | - |
| | .oOo.oOo.oOo.oOo.oOo.oOo.oOo.
| | |
Prop types are exposed for convenience:
import type { PieChartProps } from 'react-minimal-pie-chart';
About data
prop
data
prop expects an array of chart entries as follows:type Data = {
color: string;
value: number;
key?: string | number;
title?: string | number;
[key: string]: any;
}[];
Each entry accepts any custom property plus the following optional ones:
key
: custom value to be used as segments element keys
title
:title
element rendered as segment's child
Custom labels with label
render prop
label
prop accepts a function returning the string, number or element rendered as label for each segment:<PieChart
label={(labelRenderProps: LabelRenderProps) =>
number | string | React.ReactElement | undefined | null
}
/>
The function receives
labelRenderProps
object as single argument:type LabelRenderProps = {
x: number;
y: number;
dx: number;
dy: number;
textAnchor: string;
dataEntry: {
...props.data[dataIndex]
// props.data entry relative to the label extended with:
startAngle: number;
degrees: number;
percentage: number;
};
dataIndex: number;
style: React.CSSProperties;
};
Label prop, common scenarios
Render entries' values as labels:label={({ dataEntry }) => dataEntry.value}
Render segment's percentage as labels:
label={({ dataEntry }) => `${Math.round(dataEntry.percentage)} %`}
See examples in the demo sourcedemo-label-source.
How to
User interactions with the chart
See demodemo-interaction and relative source heredemo-interaction-source and heredemo-interaction-2-source.Custom tooltip
See demodemo-tooltip and relative sourcedemo-tooltip-source.Browsers support
Here is an updated browsers support list π.The main requirement of this library is an accurate rendering of SVG Stroke properties.
Please consider that
Math.sign
and Object.assign
polyfills are required to support legacy browsers.Misc
How svg arc paths work?
- http://xahlee.info/js/svgcirclearc.html
- https://codepen.io/lingtalfi/pen/yaLWJG
How SVG animations work?
This library uses thestroke-dasharray
+ stroke-dashoffset
animation strategy described here.Todo's
- Consider moving storybook deployment to CI
- Consider using
transform
to mutate segments/labels positions - Consider abstracting React bindings to re-use business logic with other frameworks
- Provide a way to supply
svg
element with any extra prop - Find a better solution to assign default props