logo

G2

  • Docs
  • Chart Introduction
  • API
  • Examples
  • Theme
  • Ecosystem
  • Productsantv logo arrow
  • 5.3.3
  • 📈 Chart Introduction
  • Mosaic Plot
  • Bar Chart
  • Bubble Chart
  • Color Map
  • Histogram Chart
  • Radial Bar Chart
  • Stacked Bar Chart
  • Area Chart
  • Box Plot
  • Bubble Map
  • Radar Chart
  • Bi-directional Bar Chart
  • Multi-set Bar Chart
  • Donut Chart
  • Heatmap
  • Choropleth Map
  • Funnel Chart
  • K-Chart
  • Gauge Chart
  • Contour Line Chart
  • Bullet Chart
  • Sankey Diagram
  • Chord Diagram

Donut Chart

Previous
Multi-set Bar Chart
Next
Heatmap

Resources

Ant Design
Galacea Effects
Umi-React Application Framework
Dumi-Component doc generator
ahooks-React Hooks Library

Community

Ant Financial Experience Tech
seeconfSEE Conf-Experience Tech Conference

Help

GitHub
StackOverflow

more productsMore Productions

Ant DesignAnt Design-Enterprise UI design language
yuqueYuque-Knowledge creation and Sharing tool
EggEgg-Enterprise-class Node development framework
kitchenKitchen-Sketch Tool set
GalaceanGalacean-互动图形解决方案
xtechLiven Experience technology
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

donut

Introduction to Donut Charts

A donut chart (also known as a doughnut chart) is essentially a pie chart with its center area removed. Donut charts encourage us to focus more on arc length rather than area, making it relatively simple to compare different donut charts.

While donut charts and pie charts are similar in terms of data representation, donut charts have their unique advantages:

  • Better Comparison: Pie charts have strong visual unity, causing viewers to focus on comparing the proportional relationships between slices within a single chart. However, when comparing two pie charts side by side, pie charts make it difficult to compare across different charts. Donut charts solve this problem.
  • Better Space Utilization: Donut charts can utilize their hollow center area to display text information such as titles, totals, or other important data.

Other Names: Doughnut Chart

Components of a Donut Chart

donut-structure
Chart TypeDonut Chart
Suitable DataA dataset containing one categorical field and one numerical field
FunctionalityCompare the size of numerical values across categories
Data MappingCategorical data maps to arc colors
Numerical data maps to arc angles
Proportional relationships shown by arc size
Data Size LimitRecommended for no more than 9 data points

Use Cases of Donut Charts

Suitable Use Cases

Example 1: Displaying Categorical Proportions

This usage is similar to pie charts. The chart below shows sales data from a gaming company:

GenreSales
Sports27,500
Strategy11,500
Action6,000
Shooter3,500
Other1,500

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'interval',
autoFit: true,
transform: [{ type: "stackY" }], // Add stackY transform
data: [
{ genre: 'Sports', sold: 27500 },
{ genre: 'Strategy', sold: 11500 },
{ genre: 'Action', sold: 6000 },
{ genre: 'Shooter', sold: 3500 },
{ genre: 'Other', sold: 1500 },
],
coordinate: { type: 'theta', innerRadius: 0.5 },
encode: { y: 'sold', color: 'genre' },
legend: { color: { position: 'bottom', layout: { justifyContent: 'center' } } },
labels: [
{
text: 'genre',
style: {
fontWeight: 'bold',
},
},
{
text: (d, i, data) => {
const total = data.reduce((acc, curr) => acc + curr.sold, 0);
const percent = ((d.sold / total) * 100).toFixed(2);
return `${percent}%`;
},
style: {
fontSize: 10,
dy: 12,
},
},
],
});
chart.render();

Explanation:

  • The genre field maps to color to distinguish different game types
  • The sold field maps to angle to represent the proportion of sales
  • Using coordinate: { type: 'theta', innerRadius: 0.5 } creates the donut effect

Example 2: Displaying Additional Information in the Center

The hollow center area of donut charts can be used to display totals, titles, or other important information:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
const data = [
{ type: 'Mobile', value: 54.2 },
{ type: 'Desktop', value: 32.1 },
{ type: 'Tablet', value: 13.7 },
];
const total = data.reduce((acc, curr) => acc + curr.value, 0);
chart.options({
type: 'interval',
autoFit: true,
data,
coordinate: { type: 'theta', innerRadius: 0.6 },
encode: { y: 'value', color: 'type' },
style: { stroke: '#fff', lineWidth: 2 },
legend: { color: { position: 'bottom', layout: { justifyContent: 'center' } } },
labels: [
{
text: (d) => `${d.value}%`,
style: {
fontWeight: 'bold',
fontSize: 12,
},
},
],
annotations: [
{
type: 'text',
style: {
text: `Total\n${total.toFixed(1)}%`,
x: '50%',
y: '50%',
textAlign: 'center',
fontSize: 16,
fontWeight: 'bold',
fill: '#8c8c8c',
},
},
],
});
chart.render();

Unsuitable Use Cases

Example 1: Too Many Categories

The chart below shows population proportions by province. Due to the excessive number of categories, it's difficult to clearly compare population data across provinces. In such cases, we recommend using bar charts.

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'interval',
autoFit: true,
data: [
{ province: 'Beijing', population: 19612368 },
{ province: 'Tianjin', population: 12938693 },
{ province: 'Hebei', population: 71854210 },
{ province: 'Shanxi', population: 27500000 },
{ province: 'Inner Mongolia', population: 24706291 },
{ province: 'Liaoning', population: 43746323 },
{ province: 'Jilin', population: 27452815 },
{ province: 'Heilongjiang', population: 38313991 },
{ province: 'Shanghai', population: 23019196 },
{ province: 'Jiangsu', population: 78660941 },
{ province: 'Zhejiang', population: 54426891 },
{ province: 'Anhui', population: 59500468 },
{ province: 'Fujian', population: 36894217 },
{ province: 'Jiangxi', population: 44567797 },
{ province: 'Shandong', population: 95792719 },
{ province: 'Henan', population: 94029939 },
{ province: 'Hubei', population: 57237727 },
{ province: 'Hunan', population: 65700762 },
{ province: 'Guangdong', population: 104320459 },
{ province: 'Guangxi', population: 46023761 },
{ province: 'Hainan', population: 8671485 },
{ province: 'Chongqing', population: 28846170 },
{ province: 'Sichuan', population: 80417528 },
{ province: 'Guizhou', population: 34748556 },
{ province: 'Yunnan', population: 45966766 },
{ province: 'Tibet', population: 3002165 },
{ province: 'Shaanxi', population: 37327379 },
{ province: 'Gansu', population: 25575263 },
{ province: 'Qinghai', population: 5626723 },
],
coordinate: { type: 'theta', innerRadius: 0.4 },
encode: { y: 'population', color: 'province' },
legend: false, // Too many categories, disable legend
labels: false, // Too many categories, disable labels
});
chart.render();

Explanation: The chart above has too many categories, making colors difficult to distinguish and labels severely overlapping, making it unsuitable for donut charts.

Example 2: Similar Proportions Among Categories

In the chart below, different game genres have similar sales volumes with very small angular differences, making donut charts unsuitable. In this case, bar charts would be more appropriate.

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'interval',
autoFit: true,
data: [
{ genre: 'Sports', sold: 15000 },
{ genre: 'Strategy', sold: 14900 },
{ genre: 'Action', sold: 15050 },
{ genre: 'Shooter', sold: 13000 },
{ genre: 'Other', sold: 13900 },
],
coordinate: { type: 'theta', innerRadius: 0.5 },
encode: { y: 'sold', color: 'genre' },
legend: { color: { position: 'bottom', layout: { justifyContent: 'center' } } },
labels: [
{
text: (d, i, data) => {
const total = data.reduce((acc, curr) => acc + curr.sold, 0);
const percent = ((d.sold / total) * 100).toFixed(2);
return `${percent}%`;
},
style: {
fontSize: 10,
},
},
],
});
chart.render();

Explanation: Each category in the chart above has a proportion close to 20%, with very small differences that are difficult to clearly compare through angular sizes.

Extensions of Donut Charts

Faceted Donut Charts

Using G2's faceting functionality, grouped data can be rendered as multiple donut charts. The chart below shows the profit proportions of the world's largest 1000 banks by region in 2007 and 2011:

YearRegionProfit (Billion USD)
2007Asia Pacific1485.54
2007Africa & Middle East330.12
2007Latin America196.5
.........
2011Asia Pacific4107.18
2011Africa & Middle East495.3
2011Latin America495.3
.........

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'facetRect',
autoFit: true,
data: [
{ year: '2007', area: 'Asia Pacific', profit: 1485.54 },
{ year: '2007', area: 'Western Europe', profit: 3631.32 },
{ year: '2007', area: 'North America', profit: 2083.9 },
{ year: '2007', area: 'Africa & Middle East', profit: 330.12 },
{ year: '2007', area: 'Central & Eastern Europe', profit: 141.48 },
{ year: '2007', area: 'Latin America', profit: 196.5 },
{ year: '2011', area: 'Asia Pacific', profit: 4107.18 },
{ year: '2011', area: 'Western Europe', profit: 480.06 },
{ year: '2011', area: 'North America', profit: 1783.08 },
{ year: '2011', area: 'Africa & Middle East', profit: 495.3 },
{ year: '2011', area: 'Central & Eastern Europe', profit: 259.08 },
{ year: '2011', area: 'Latin America', profit: 495.3 },
],
encode: { x: 'year' },
children: [
{
type: 'interval',
transform: [{ type: "stackY" }], // Add stackY transform
coordinate: { type: 'theta', innerRadius: 0.5 },
encode: { y: 'profit', color: 'area' },
legend: { color: { position: 'bottom', layout: { justifyContent: 'center' } } },
labels: [
{
text: (d, i, data) => {
const total = data.reduce((acc, curr) => acc + curr.profit, 0);
const percent = ((d.profit / total) * 100).toFixed(1);
return `${percent}%`;
},
style: {
fontSize: 10,
},
},
],
},
],
});
chart.render();

Comparing Donut Charts to Other Charts

Donut Charts and Pie Charts

  • Similarities: Both are used to display proportional relationships of categorical data
  • Differences:
    • Donut charts have a hollow center that can accommodate additional information
    • Donut charts emphasize arc length (circumference), while pie charts emphasize area
    • Donut charts perform better when comparing multiple charts

Donut Charts and Bar Charts

  • Donut Charts: Better suited for showing proportional relationships, emphasizing part-to-whole relationships
  • Bar Charts: Better suited for precise numerical comparisons, especially when value differences are small

Donut Charts and Nightingale Charts (Rose Diagrams)

  • Donut Charts: Represent values through angles, with fixed inner radius
  • Nightingale Charts: Represent values through radius, making value differences easier to distinguish

Similar Charts

Categories

Radial Bar Chart
Radial Bar Chart
Comparison
Proportion