# Pie & Sliced Charts — Pie, Donut, Funnel, Pyramid
## Required imports
### ES modules
```ts
import * as am5 from "@amcharts/amcharts5";
import * as am5percent from "@amcharts/amcharts5/percent";
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
```
### CDN
```html
```
## Pie / Donut chart setup
```js
const root = am5.Root.new("chartdiv");
root.setThemes([am5themes_Animated.new(root)]);
const chart = root.container.children.push(
am5percent.PieChart.new(root, {
layout: root.verticalLayout,
// Donut: set innerRadius
// innerRadius: am5.percent(50)
})
);
const series = chart.series.push(
am5percent.PieSeries.new(root, {
name: "Sales",
valueField: "value",
categoryField: "category"
})
);
// Data — LAST
series.data.setAll([
{ category: "Phones", value: 501 },
{ category: "Tablets", value: 301 },
{ category: "Laptops", value: 201 }
]);
series.appear(1000);
chart.appear(1000, 100);
```
### PieChart key settings
| Setting | Type | Description |
|---------|------|-------------|
| `radius` | percent/number | Outer radius (default: `am5.percent(80)`) |
| `innerRadius` | percent/number | Inner hole for donut (default: 0). Percent is relative to radius |
| `startAngle` | number | Start angle in degrees (default: -90) |
| `endAngle` | number | End angle in degrees (default: 270) |
**Semi-circle pie:** `startAngle: 180, endAngle: 360` (set on BOTH PieChart AND PieSeries)
### PieSeries key settings
| Setting | Type | Description |
|---------|------|-------------|
| `valueField` | string | Data field for values (required) |
| `categoryField` | string | Data field for categories (required) |
| `alignLabels` | boolean | Align labels in column (default: true). Set false for radial/inside labels |
| `legendLabelText` | string | Legend label format, e.g. `"{category}"` |
| `legendValueText` | string | Legend value format, e.g. `"{value}"` |
| `startAngle` | number | Start angle in degrees (default: inherits from chart). Must match PieChart's startAngle for semi-circle |
| `endAngle` | number | End angle in degrees (default: inherits from chart). Must match PieChart's endAngle for semi-circle |
### Labels
```js
// Standard aligned labels (default)
series.labels.template.setAll({
text: "{category}: {valuePercentTotal.formatNumber('0.0')}%",
fontSize: 12
});
// Radial labels
series.set("alignLabels", false);
series.labels.template.setAll({
textType: "radial",
centerX: am5.percent(100),
text: "{category}"
});
// Inside labels
series.labels.template.setAll({
inside: true,
radius: 10,
text: "{valuePercentTotal.formatNumber('0')}%"
});
// Hide labels
series.labels.template.set("forceHidden", true);
series.ticks.template.set("forceHidden", true);
```
### Slice appearance
```js
series.slices.template.setAll({
strokeWidth: 2,
stroke: am5.color(0xffffff),
cornerRadius: 5,
tooltipText: "{category}: {valuePercentTotal.formatNumber('0.0')}% ({value})"
});
// Click to pull out slice
series.slices.template.set("toggleKey", "active");
series.slices.template.states.create("active", {
shiftRadius: 20 // pixels to pull out
});
```
### Custom colors
```js
// Set colors per slice from data
series.slices.template.adapters.add("fill", function(fill, target) {
return chart.get("colors").getIndex(series.slices.indexOf(target));
});
// Or in data:
// { category: "A", value: 100, sliceSettings: { fill: am5.color(0xff0000) } }
// series.slices.template.set("templateField", "sliceSettings");
```
## Funnel chart setup
```js
const chart = root.container.children.push(
am5percent.SlicedChart.new(root, {
layout: root.horizontalLayout
})
);
const series = chart.series.push(
am5percent.FunnelSeries.new(root, {
name: "Funnel",
valueField: "value",
categoryField: "stage",
orientation: "vertical", // "vertical" or "horizontal"
bottomRatio: 0, // 0 = trapezoids (classic funnel), 1 = rectangles
alignLabels: true
})
);
series.data.setAll([
{ stage: "Prospects", value: 1000 },
{ stage: "Qualified", value: 600 },
{ stage: "Proposals", value: 300 },
{ stage: "Closed", value: 100 }
]);
```
### FunnelSeries key settings
| Setting | Type | Description |
|---------|------|-------------|
| `orientation` | `"vertical" \| "horizontal"` | Direction of the funnel (required) |
| `bottomRatio` | number (0–1) | 0 = trapezoids (classic funnel), 1 = rectangles (default) |
| `alignLabels` | boolean | Align labels in a column (default: true) |
### Slice links (connectors between funnel slices)
```js
series.links.template.setAll({
fillOpacity: 0.5,
height: 10 // gap between slices
});
```
## Pyramid chart setup
```js
const series = chart.series.push(
am5percent.PyramidSeries.new(root, {
name: "Pyramid",
valueField: "value",
categoryField: "level",
orientation: "vertical",
valueIs: "area", // "area" (default) or "height"
topWidth: am5.percent(0), // tip width
bottomWidth: am5.percent(100) // base width
})
);
```
### PyramidSeries extra settings
| Setting | Type | Description |
|---------|------|-------------|
| `valueIs` | `"area" \| "height"` | How value maps to size (area is recommended) |
| `topWidth` | percent/number | Width of pyramid tip |
| `bottomWidth` | percent/number | Width of pyramid base |
## Pictorial Stacked chart setup
Pictorial charts use an SVG path as a mask to create shaped charts (e.g., human figure, bottle, battery). Uses `SlicedChart` (same as funnel/pyramid) with `PictorialStackedSeries`.
```js
// Use SlicedChart — same as funnel and pyramid
const chart = root.container.children.push(
am5percent.SlicedChart.new(root, {
layout: root.verticalLayout
})
);
// SVG path that defines the shape (any SVG path string works)
const humanShape = "M53.5,476c0,14,6.833,21,20.5,21s20.5-7,20.5-21V287h21v189c0,14,6.834,21,20.5,21c13.667,0,20.5-7,20.5-21V154h10v116c0,7.334,2.5,12.667,7.5,16s10.167,3.333,15.5,0s8-8.667,8-16V145c0-13.334-4.5-23.667-13.5-31s-21.5-11-37.5-11h-82c-15.333,0-27.833,3.333-37.5,10s-14.5,17-14.5,31v133c0,6,2.667,10.333,8,13s10.5,2.667,15.5,0s7.5-7,7.5-13V154h10V476 M61.5,42.5c0,11.667,4.167,21.667,12.5,30S92.333,85,104,85s21.667-4.167,30-12.5S146.5,54,146.5,42c0-11.335-4.167-21.168-12.5-29.5C125.667,4.167,115.667,0,104,0S82.333,4.167,74,12.5S61.5,30.833,61.5,42.5z";
const series = chart.series.push(
am5percent.PictorialStackedSeries.new(root, {
name: "Survey",
categoryField: "stage",
valueField: "value",
orientation: "vertical", // "vertical" | "horizontal"
svgPath: humanShape, // SVG path string for the mask shape
// startLocation: 0, // 0–1, where fill starts
// endLocation: 1, // 0–1, where fill ends
})
);
series.data.setAll([
{ stage: "Applied", value: 600 },
{ stage: "Phone Screen", value: 300 },
{ stage: "Interview", value: 150 },
{ stage: "Offer", value: 50 },
{ stage: "Hired", value: 30 }
]);
```
### Pictorial key settings
| Setting | Type | Description |
|---------|------|-------------|
| `svgPath` | string | SVG path string defining the mask shape (required) |
| `orientation` | `"vertical"` \| `"horizontal"` | Fill direction |
| `startLocation` | number (0–1) | Where the fill starts within the shape |
| `endLocation` | number (0–1) | Where the fill ends within the shape |
| `alignLabels` | boolean | Align labels outside the shape |
**Getting SVG paths:** Use any vector editor (Adobe Illustrator, Inkscape, Figma) to draw a shape and export as SVG, then extract the `d` attribute from the `` element.
**Pictorial fraction chart:** Use `startLocation` and `endLocation` to show a percentage fill of a single shape (e.g., a battery at 75%):
```js
am5percent.PictorialStackedSeries.new(root, {
svgPath: batteryPath,
startLocation: 0,
endLocation: 0.75, // 75% filled
// ...
})
```
## Legend (for all percent charts)
```js
const legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.percent(50),
x: am5.percent(50),
layout: root.horizontalLayout
}));
// IMPORTANT: Use series.dataItems, NOT chart.series.values
legend.data.setAll(series.dataItems);
```
**Custom legend labels:**
```js
am5percent.PieSeries.new(root, {
legendLabelText: "[{fill}]{category}[/]",
legendValueText: "[bold {fill}]{value}[/]",
// ...
});
```
## Nested / Multi-level pie (concentric rings)
```js
// Outer ring
var outerSeries = chart.series.push(am5percent.PieSeries.new(root, {
valueField: "value",
categoryField: "category",
radius: am5.percent(95),
innerRadius: am5.percent(60)
}));
// Inner ring
var innerSeries = chart.series.push(am5percent.PieSeries.new(root, {
valueField: "value",
categoryField: "category",
radius: am5.percent(55),
innerRadius: am5.percent(20)
}));
outerSeries.data.setAll(outerData);
innerSeries.data.setAll(innerData);
```
## Data-driven slice colors (templateField)
```js
series.slices.template.set("templateField", "sliceSettings");
series.data.setAll([
{ category: "Critical", value: 40, sliceSettings: { fill: am5.color(0xff0000) } },
{ category: "Warning", value: 35, sliceSettings: { fill: am5.color(0xffa500) } },
{ category: "OK", value: 25, sliceSettings: { fill: am5.color(0x00cc00) } }
]);
```
## Events on slices
```js
series.slices.template.events.on("click", function(ev) {
var data = ev.target.dataItem.dataContext;
console.log("Clicked:", data.category, data.value);
});
series.slices.template.events.on("pointerover", function(ev) {
ev.target.set("scale", 1.05);
});
series.slices.template.events.on("pointerout", function(ev) {
ev.target.set("scale", 1);
});
```
## Disposal
```js
root.dispose();
```
---
# amCharts 5 Pie & Sliced Charts — Working Examples
## Example 1: Basic pie chart with legend
```html
Pie Chart
```
## Example 2: Donut chart with center label
```html
Donut Chart
```
## Example 3: Semi-circle pie
```html
Semi-Circle Pie
```
## Example 4: Funnel chart
```html
Funnel Chart
```
## Example 5: Pyramid chart
```html
Pyramid Chart
```