Pie
Overview
A pie chart splits a circle into slices, one per label, with each slice's angle proportional to its value. Use it to show how a whole divides into a few parts, especially when one or two parts dominate: "more than half", "about a quarter". A donut (hole) works the same way and leaves room for a total or a title in the middle.
Pick a different chart when:
- you compare more than about six parts, or parts of similar size: angles are hard to compare, so use a sorted horizontal bar chart;
- you compare the same parts across several groups: use stacked or grouped bars rather than several pies;
- the values don't add up to a meaningful whole (averages, rates, values that can be negative);
- the parts form a hierarchy: use a sunburst or a treemap.
Minimal example
import { createChart } from '@mk7s/holochart';
const chart = createChart(document.getElementById('chart')!, {
data: [
{
type: 'pie',
labels: ['Housing', 'Food', 'Transport', 'Savings'],
values: [1450, 620, 380, 540],
},
],
});Slices are sorted largest first (sort: true) and drawn counterclockwise from 12 o'clock, each labeled with its percent. The legend lists one item per label:
pie/basicData format
values: the size of each slice. Negative values andnull/NaNare skipped; zeros are kept (they get a legend item but no area).labels: the name of each slice, shown in the legend, hover, andtextinfo. Slices with the same label are merged and their values added, so you can pass raw rows and let the pie aggregate them.- Without
values, each label counts once:labels: ['a', 'b', 'a']drawsaat 2/3 andbat 1/3, which counts categories without a pre-aggregation step. - Without
labels, slices are namedlabel0,label0 + dlabel, … (defaults 0 and 1). textandhovertext: extra per-slice strings fortextinfo: 'text',%{text}in templates, and hover.- Plain arrays and typed arrays (
Float64Array) both work forvalues.
Variations
Donut with a centered title
hole (0 to 1) is the fraction of the radius cut out of the middle. With a hole, title.position: 'middle center' puts the trace title inside it, a good place for the total. Title text accepts <b>, <i>, and <br>.
pie/donutPulled slices and outside labels
pull moves slices out from the center by a fraction of the radius: one number for every slice, or an array with one entry per slice to emphasize a few. The pie shrinks so the largest pull still fits. textposition: 'outside' puts labels around the pie with leader lines; 'inside' keeps them in the slices, and 'auto' (the default) puts each label inside when it fits and outside when it doesn't. rotation (degrees) turns the start angle, and direction: 'clockwise' reverses the order.
pie/pulledMany slices and collision avoidance
With many small slices, outside labels would overlap. Holochart spreads them apart vertically on each side of the pie, like Plotly, and draws a leader line from each label to its slice. Give outside labels room with layout.margin: pie labels don't push the margins yet.
pie/many-slicesMore than a dozen slices is usually a sign to group the tail into an "Other" slice or to switch to a sorted bar chart.
Text info, templates, and orientation
textinfo picks what each slice shows: any of label, text, value, and percent joined with + ('label+percent'), or 'none'. For full control, texttemplate formats the text with %{label}, %{value}, %{percent}, %{text}, and %{customdata}, plus d3 formats: '%{label}<br>%{value:$,.0f}'.
insidetextorientation sets how labels inside slices are turned: 'horizontal' keeps them level (shrinking them to fit thin slices), 'radial' runs them along the radius, 'tangential' along the circle, and 'auto' (the default) picks whichever fits the label largest, per slice. Fonts come from textfont, overridden by insidetextfont and outsidetextfont; inside labels switch between dark and light text to contrast with the slice color unless you set a color.
pie/text-orientationMultiple pies in a grid with scalegroup
Each pie has a domain: the part of the plot area it fills (domain.x, domain.y as fractions). Simpler, set layout.grid: { rows, columns } and pick a cell with domain.row and domain.column. A pie stays round and centered in its cell.
By default every pie fills its cell, so a pie of 400 looks as big as a pie of 900. Give the pies the same scalegroup to make their areas proportional to their totals. The legend shows each label once, and a legend click hides that label in every pie.
pie/grid-scalegroupPattern fills
marker.pattern.shape hatches each slice with its own pattern, in the slice color on the paper color (see Patterns & textures). The legend shows the patterns too.
pie/patternsStyling
- Colors.
marker.colorssets one color per slice. Without it, slices take their colors fromlayout.piecolorway(default: thecolorway), by label: the same label gets the same color in every pie of the figure.layout.extendpiecolors(defaulttrue) extends the colorway with lighter and darker variants once it runs out, instead of repeating colors, which matters for pies with more than ten slices. - Outlines.
marker.line.colorandmarker.line.widthdraw slice borders. The default look separates slices with a 1 px line in the background color; on a light theme, a white 1–2 px outline separates neighbors well, especially on donuts. - Shape.
holefor donuts,pullto pull slices out,rotationanddirectionfor the start angle and order,sort: falseto keep the input order. - Text.
textinfo,texttemplate,textposition,insidetextorientation, andtextfont,insidetextfont,outsidetextfont. - Title.
title.text,title.font, andtitle.position:'top left','top center'(the default),'top right','middle center'(inside the hole),'bottom left','bottom center', or'bottom right'. - Patterns.
marker.patternhatches the slices:shape,size,solidityand colors per slice, andfillmode(see Patterns & textures).
Interactivity
Hover. Hovering a slice shows its label.
hoverinfopicks the parts, any oflabel,text,value,percent, andnamejoined with+(default: all of them). For full control, usehovertemplate, for example'%{label}: %{value} (%{percent})<extra></extra>'. In templates%{percent}is already formatted ('41.7%');%{value}takes d3 formats such as%{value:,.0f}. A pie always shows the label of the slice under the pointer, whateverhovermodesays.Legend. A pie adds one legend item per label, not one per trace. Clicking an item hides that slice and the others re-flow to fill the circle, with percents recomputed over the visible slices. Double-click an item to show only that label, and double-click it again to show them all. The hidden labels are kept in
layout.hiddenlabels, so you can also set them yourself:tsawait chart.relayout({ hiddenlabels: ['Other'] });Events.
hover,unhover, andclickcarry Plotly-shaped points:curveNumber,pointNumber(the index invalues),label,value,percent(a fraction,0.25),text, andcolor.legendclickandlegenddoubleclickcarrycurveNumberand the item'slabel; returnfalsefrom a listener to cancel the default hide or isolate:tschart.on('click', (e) => console.log(e.points[0]?.label)); chart.on('legendclick', (e) => e.label !== 'Other'); // "Other" can't be hiddenSee the events reference.
Pies have no axes, so zoom, pan, and box or lasso selection don't apply to them.
3D-native options
Holochart extensions (full bundle), see Extrusion & 2.5D:
depth: the pie's thickness in px, a percentage of the radius ('20%'), or one number per slice (perlabelsentry) for a height-encoded pie.0(default) draws a flat pie.tilt: lays the pie back, degrees (±80);0(default) is the flat view.perspective(0–1, default 0.5): 0 gives the classic parallel projection.bevel.sizeandbevel.segments: rounded edges.material: Plotly's lighting model (default),flat, or a three.js material type.- A donut's
holemakes annular slices;pullmoves slices out in 3D;marker.linebecomes a gap between the slices. Labels (inside and outside, with leader lines) sit on the slices' tops; hover, click and legend clicks work on the tilted pie, andtiltanimates withanimateandreact.
pie/depthpie/depth-donutpie/depth-heightpie/depth-explodedpie/depth-tiltReading a 3D pie
A 3D pie is harder to read than a flat one, which is already harder to read than a bar chart: people compare angles and areas less accurately than lengths. Tilting adds distortion — slices in front look bigger than equal slices at the back, and only the front slices show their sides — so the same share looks different depending on where it is. Use a 3D pie for presentation, with the shares labelled (textinfo: 'percent'), and a flat pie or a bar chart when readers need to compare the parts. Heights in a height-encoded pie are foreshortened too: label them, and prefer perspective: 0 so equal heights look equal.
Performance notes
- Pies are small data: rendering cost is not the limit, readability is. Hundreds of slices draw fine but can't be read, so aggregate the tail into an "Other" slice first.
- Hover finds the slice from the pointer's angle and distance to the pie's center, so it doesn't depend on the number of slices.
- Labels are text, which is typeset asynchronously, so they can appear a frame or two after the slices. Outside labels also need a placement pass to avoid collisions; with many slices, use
textposition: 'inside'or'none'and rely on hover and the legend. - Hiding a slice from the legend is a
relayoutofhiddenlabels: the pie re-flows without re-sending the data.
Accessibility notes
- Screen readers: the chart is a
<canvas>. The DOM mirror that describes slices to assistive technology is not built yet (planned for M2, see the accessibility guide). Add a caption oraria-labelthat states the main split, and a table of the values. - Keyboard: Tab moves into the plot area; the arrow keys then step through the slices, each showing its hover label. See the keys by chart family.
- Color: label slices directly (
textinfo: 'label+percent') so readers don't have to match legend colors, keep the number of slices small, and separate slices with outlines in the background color. Pattern fills (marker.pattern) tell slices apart in print and for color-blind readers.
Attribute reference
See the pie attribute reference for every attribute, its type, and its default. The pie layout options piecolorway, extendpiecolors, hiddenlabels, and grid are in the layout reference.
Related charts
- Bar: compare parts precisely, or the same parts across groups (stacked bars)
- Horizontal bar: many parts, sorted, with long labels
- Sunburst and treemap: parts that form a hierarchy
- Funnel area: a pie-like funnel
Plotly migration notes
- Attribute names and defaults match Plotly's
pietrace:values,labels,label0/dlabel,hole,pull,rotation,direction(default'counterclockwise'),sort,marker.colors,textinfo,texttemplate,textposition,insidetextorientation,title,scalegroup,domain,hoverinfo, andhovertemplate, as do the layout attributespiecolorway,extendpiecolors,hiddenlabels, andgrid. Plotly pie figures carry over unchanged. - Legend click and double-click update
layout.hiddenlabelsas in Plotly, and the events carry the same fields (includinglabelon legend events). - Differences and not supported yet:
- Hiding or showing a slice re-flows the others at once; the animated transition is planned. Pulled-slice transitions are planned too.
marker.pattern.path(custom SVG pattern tiles); withfillmode: 'overlay'each slice overlays its own color (see the pattern differences).layout.uniformtext(one font size for all slice labels).automarginon pies: outside labels don't push the margins yet, so setlayout.marginwide enough for them.
- Pie extrusion (
depth,tilt) is a planned Holochart extension (plan E9.12).