Pie and donut
Setting chart.type to 'pie' renders the series as pie slices instead of an x/y plot. The createPie helper builds the pieces from labelled values: every slice is its own series, so the legend, focus and filtering behave exactly like the other chart types.
// createPie turns labelled values into pie pieces: every slice is its own
// series (so the legend lists the slices and clicking one filters it),
// and the data is a single row holding every slice value.
import { createPie } from '@mochart/core';
import type { MochartInputConfig } from '@mochart/core';
const pie = createPie(
[
{ label: 'Subscriptions', value: 420 },
{ label: 'Services', value: 210 },
{ label: 'Hardware', value: 140 },
{ label: 'Licensing', value: 75 },
{ label: 'Support', value: 65 },
{ label: 'Other', value: 30 }
],
// valuePercent puts each slice's share next to its value in the tooltip,
// e.g. "420 (48.8%)"
{ valueFormat: ',.0f', tooltipValues: 'valuePercent' }
);
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Revenue by Product (fictional, $k)' },
// chart.type 'pie' swaps the axis plot for the radial plot.
chart: pie.chart,
pie: pie.pie,
categoryAxis: pie.categoryAxis,
series: pie.series
};
export const data = pie.data;How it works
createPiereturns config fragments (like the other chart-type helpers): achartfragment setting the type, acategoryAxisnaming the single category column, and one series per slice. The data is a single row —{ category: 'all', slice0: 420, slice1: 210, ... }.- Slices are series. Hovering a slice or its legend entry focuses it, and clicking a legend entry filters it — the remaining slices grow to fill the circle, animated with the usual
animationtiming. Slice colors come from thecolorPaletteby series index, or from an explicit per-itemcolor. - On first load the pie sweeps in clockwise from the start angle over
animation.initialDuration(slice labels appear once the sweep settles). SettingfocusOffsetFraction"explodes" the focused slice away from the center, animated by the focus tween — try hovering the legend on the donut below. - Clicking the chart opens the tooltip with one row per slice. In pie mode
tooltip.snapToCategorydefaults tofalse, so the tooltip anchors at the click point, andtooltip.showCategorydefaults tofalse— a pie has a single category, so its value (createPiewrites'all') would head every tooltip. SetshowCategory: truewith a meaningfulcategoryValueif you want that line back. - The category and value axes still exist structurally (the category column and value domains feed the data model and animations) but default to
visible: falsein pie mode. The crosshair does not apply. - Values must be non-negative:
createPieclamps negatives to 0, and a zero-value slice simply doesn't render. Only the first data row is rendered.
Donut and slice labels
An inner radius via pie.innerRadiusFraction turns the pie into a donut — the helper's donut shorthand sets it to 0.6, and its own innerRadiusFraction option picks the exact value — and pie.showLabels puts value, percent or title labels at the slice centroids.
// The donut option adds an inner radius, and tooltipValues 'percent' makes the
// tooltip show each slice's share instead of its raw value. The chart computes
// those percentages from the current slice shares, so — like the percent slice
// labels below — they renormalize as slices are filtered.
import { createPie } from '@mochart/core';
import type { MochartInputConfig } from '@mochart/core';
const donut = createPie(
[
{ label: 'Chrome', value: 62 },
{ label: 'Safari', value: 20 },
{ label: 'Edge', value: 6 },
{ label: 'Firefox', value: 5 },
{ label: 'Opera', value: 3 },
{ label: 'Other', value: 4 }
],
{ donut: true, tooltipValues: 'percent' }
);
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Browser Market Share (fictional)' },
chart: donut.chart,
// showLabels puts percent labels at the slice centroids (slices thinner
// than labelMinFraction hide theirs), and focusOffsetFraction explodes
// the hovered slice away from the center.
pie: { ...donut.pie, showLabels: true, labelType: 'percent', focusOffsetFraction: 0.05 },
categoryAxis: donut.categoryAxis,
series: donut.series
};
export const data = donut.data;labelTypepicks the label content: a single part ('value','percent'or'title') or a combination —'valuePercent'for420 (45%),'percentValue'for45% (420),'titleValue'forSubscriptions: 420and'titlePercent'forSubscriptions: 45%.labelValueFormatandlabelPercentFormatformat the two numeric parts independently (percent parts format the fraction, so specifiers like'.1%'apply). Slices thinner thanlabelMinFractionhide their labels. Label colors reuse the per-serieslabelTextStylestyle — each slice is a series, so a slice's label is painted by its own series entry. When slices are filtered via the legend, percent labels renormalize against the remaining slices — setadjustLabelsForFilteringtofalseto keep every slice's share of the full total instead.tooltipValuesdoes the same for the tooltip rows:'value'(the default),'percent', or the'valuePercent'/'percentValue'combinations. The value part keeps its per-series formatting (valueFormat,valuePrefix,valueSuffix) — the helper'svalueFormatoption stamps one format onto every slice's series; the percent part is formatted bytooltipPercentFormat. The helper'stooltipValuesoption forwards straight to it.- Tooltip percentages are computed from the same slice shares as the labels, so they renormalize as slices are filtered — set
tooltip.adjustForFilteringtofalseto keep every slice's share of the full total (the tooltip equivalent ofadjustLabelsForFiltering). A filtered slice's own row shows the usualfilteredValueCharacterplaceholder in place of both parts. - Geometry knobs:
startAnglerotates the first slice's starting edge,padAngleopens a gap between slices, andcornerRadiusrounds the slice corners.
Half pies and gauges
endAngle defaults to startAngle + 360 (a full circle, so rotating with startAngle alone never truncates the pie); setting it explicitly confines the slices to a partial span. With startAngle: -90 and endAngle: 90 the pie becomes a half-donut gauge — an endAngle smaller than startAngle runs counterclockwise.
// startAngle/endAngle confine the slices to a partial span — here a half
// donut — and the pie center can carry a label plus a live total that counts
// along with value changes and filtering.
import { createPie } from '@mochart/core';
import type { MochartInputConfig } from '@mochart/core';
const gauge = createPie(
[
{ label: 'Promoters', value: 540 },
{ label: 'Passives', value: 280 },
{ label: 'Detractors', value: 180 }
],
// percentValue pairs each segment's share with its response count, e.g.
// "54.0% (540)"
{ tooltipValues: 'percentValue' }
);
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Customer Sentiment (fictional survey)' },
chart: gauge.chart,
pie: {
...gauge.pie,
startAngle: -90,
endAngle: 90,
innerRadiusFraction: 0.55,
// a small gap and rounded corners separate the segments
padAngle: 1,
cornerRadius: 3,
showLabels: true,
labelType: 'title',
// the center total tracks the unfiltered slices, so clicking a legend
// entry counts it down; the negative Y offset lifts it off the gauge
// pivot into the hole
centerLabel: 'responses',
showCenterTotal: true,
centerTotalFormat: ',.0f',
centerOffsetYFraction: -0.25
},
categoryAxis: gauge.categoryAxis,
series: gauge.series
};
export const data = gauge.data;centerLabelputs a text line at the circle center, andshowCenterTotaladds the live total of the unfiltered slice values, formatted bycenterTotalFormat— it counts along with value tweens and filtering (click a legend entry). SetadjustCenterTotalForFilteringtofalseto keep the full total while slices are filtered.- The center content sits at the circle center (the gauge pivot);
centerOffsetXFractionandcenterOffsetYFractionnudge it by fractions of the outer radius — the example's-0.25lifts it into the hole. - The center text is styled by
centerLabelTextStyleandcenterTotalTextStyle, both defaulting tofillColor: 'currentColor'so the text follows the host page's CSScolor. It can also be restyled directly: CSS wins over the presentation attribute, so targeting.mochart-pie-center textworks (the demo dark theme does exactly this). - The layout fits the configured span's bounding box into the plot, so a half pie uses the space its missing half would waste (and the radius grows accordingly) instead of staying centered in an empty square. The span comes from the config, so the fit holds still while values animate.