logo

G2

  • 文档
  • 图表介绍
  • API
  • 图表示例
  • 主题
  • 周边生态
  • 所有产品antv logo arrow
  • 5.3.3
  • 📈 图表分类
  • 马赛克图
  • 堆叠柱状图
  • 分组柱状图
  • 气泡图
  • 色块图
  • 玉珏图
  • 直方图
  • 柱状图
  • 带气泡的地图
  • 雷达图
  • 面积图
  • 箱形图
  • 双向柱状图
  • 环图
  • 热力图
  • 分级统计地图
  • 漏斗图
  • K线图
  • 仪表盘
  • 等高线图
  • 桑基图
  • 子弹图
  • 和弦图

环图

上一篇
双向柱状图
下一篇
热力图

Resources

Ant Design
Galacea Effects
Umi-React 应用开发框架
Dumi-组件/文档研发工具
ahooks-React Hooks 库

社区

体验科技专栏
seeconfSEE Conf-蚂蚁体验科技大会

帮助

GitHub
StackOverflow

more products更多产品

Ant DesignAnt Design-企业级 UI 设计语言
yuque语雀-知识创作与分享工具
EggEgg-企业级 Node 开发框架
kitchenKitchen-Sketch 工具集
GalaceanGalacean-互动图形解决方案
xtech蚂蚁体验科技
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

donut

环图的简介

环图(又叫做甜甜圈图),其本质是饼图将中间区域挖空。环图采用了让我们更关注长度而不是面积的做法,这样我们就能相对简单的对比不同的环图。

虽然环图和饼图在数据表达上很相似,但环图还是有它独特的优点:

  • 更好的对比性:饼图的整体性太强,我们会将注意力集中在比较饼图内各个扇形之间占整体比重的关系。但如果我们将两个饼图放在一起,饼图很难同时对比两个图。环图解决了这个问题。
  • 空间利用率更高:环图可以使用它的空心区域显示文本信息,比如标题、总数等。

英文名:Donut Chart

环图的构成

donut-structure
图表类型环图
适合的数据列表:一个分类数据字段、一个连续数据字段
功能对比分类数据的数值大小
数据与图形的映射分类数据字段映射到环形的颜色
连续数据字段映射到环形的角度
适合的数据条数不超过 9 条数据

环图的应用场景

适合的场景

例子 1: 展示分类的占比情况

这种用法与饼图类似,下图是一个游戏公司的销售情况:

genre(游戏类型)sold(销售量)
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" }], // 添加堆叠转换
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();

说明:

  • genre 字段映射到颜色,用于区分不同的游戏类型
  • sold 字段映射到角度,表示销售量占比的大小
  • 使用 coordinate: { type: 'theta', innerRadius: 0.5 } 创建环图效果

例子 2: 在中心区域显示额外信息

环图的空心区域可以用来显示总数、标题或其他重要信息:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
const data = [
{ type: '移动端', value: 54.2 },
{ type: '桌面端', value: 32.1 },
{ type: '平板端', value: 13.7 },
];
const total = data.reduce((acc, curr) => acc + curr.value, 0);
chart.options({
type: 'interval',
autoFit: true,
transform: [{ type: "stackY" }], // 添加堆叠转换
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: `总计\n${total.toFixed(1)}%`,
x: '50%',
y: '50%',
textAlign: 'center',
fontSize: 16,
fontWeight: 'bold',
fill: '#8c8c8c',
},
},
],
});
chart.render();

不适合的场景

例子 1: 分类过多的场景

下图是各个省的人口的占比情况,因为这张图上包含的分类过多,很难清晰对比各个省份的人口数据占比情况,所以这种情况下,我们推荐使用柱状图。

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'interval',
autoFit: true,
transform: [{ type: "stackY" }], // 添加堆叠转换
data: [
{ province: '北京市', population: 19612368 },
{ province: '天津市', population: 12938693 },
{ province: '河北省', population: 71854210 },
{ province: '山西省', population: 27500000 },
{ province: '内蒙古自治区', population: 24706291 },
{ province: '辽宁省', population: 43746323 },
{ province: '吉林省', population: 27452815 },
{ province: '黑龙江省', population: 38313991 },
{ province: '上海市', population: 23019196 },
{ province: '江苏省', population: 78660941 },
{ province: '浙江省', population: 54426891 },
{ province: '安徽省', population: 59500468 },
{ province: '福建省', population: 36894217 },
{ province: '江西省', population: 44567797 },
{ province: '山东省', population: 95792719 },
{ province: '河南省', population: 94029939 },
{ province: '湖北省', population: 57237727 },
{ province: '湖南省', population: 65700762 },
{ province: '广东省', population: 104320459 },
{ province: '广西壮族自治区', population: 46023761 },
{ province: '海南省', population: 8671485 },
{ province: '重庆市', population: 28846170 },
{ province: '四川省', population: 80417528 },
{ province: '贵州省', population: 34748556 },
{ province: '云南省', population: 45966766 },
{ province: '西藏自治区', population: 3002165 },
{ province: '陕西省', population: 37327379 },
{ province: '甘肃省', population: 25575263 },
{ province: '青海省', population: 5626723 },
],
coordinate: { type: 'theta', innerRadius: 0.4 },
encode: { y: 'population', color: 'province' },
legend: false, // 分类太多,关闭图例
labels: false, // 分类太多,关闭标签
});
chart.render();

说明:上图中分类过多,颜色难以区分,标签重叠严重,不适合使用环图。

例子 2: 分类占比差别不明显的场景

下图中游戏公司的不同种类游戏的销售量相近,角度差异很小,不太适合使用环图,此时可以使用柱状图。

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'interval',
autoFit: true,
transform: [{ type: "stackY" }], // 添加堆叠转换
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();

说明:上图中各个分类的占比都接近 20%,差异很小,难以通过角度清晰地对比数值大小。

环图的扩展

分面环图

使用 G2 的分面功能,可以将分组数据绘制成多个环图。下图展示了全球最大1000家银行所在地区在2007年和2011年的利润总额占比情况:

年份地区利润总额(亿美金)
2007亚太地区1485.54
2007非洲及中东330.12
2007拉丁美洲196.5
………………
2011亚太地区4107.18
2011非洲及中东495.3
2011拉丁美洲495.3
………………

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
theme: 'classic',
});
chart.options({
type: 'facetRect',
autoFit: true,
data: [
{ year: '2007', area: '亚太地区', profit: 1485.54 },
{ year: '2007', area: '西欧', profit: 3631.32 },
{ year: '2007', area: '北美', profit: 2083.9 },
{ year: '2007', area: '非洲及中东', profit: 330.12 },
{ year: '2007', area: '中欧和东欧', profit: 141.48 },
{ year: '2007', area: '拉丁美洲', profit: 196.5 },
{ year: '2011', area: '亚太地区', profit: 4107.18 },
{ year: '2011', area: '西欧', profit: 480.06 },
{ year: '2011', area: '北美', profit: 1783.08 },
{ year: '2011', area: '非洲及中东', profit: 495.3 },
{ year: '2011', area: '中欧和东欧', profit: 259.08 },
{ year: '2011', area: '拉丁美洲', profit: 495.3 },
],
encode: { x: 'year' },
children: [
{
type: 'interval',
transform: [{ type: "stackY" }], // 添加堆叠转换
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();

环图与其他图表的对比

环图和饼图

  • 相似性:都用于展示分类数据的占比关系
  • 区别:
    • 环图中心留空,可以放置额外信息
    • 环图更强调弧长(周长),饼图更强调面积
    • 环图在多图对比时效果更好

环图和柱状图

  • 环图:更适合展示占比关系,强调部分与整体的关系
  • 柱状图:更适合展示精确的数值对比,特别是数值差异较小的情况

环图和南丁格尔玫瑰图

  • 环图:通过角度表示数值,内径固定
  • 南丁格尔玫瑰图:通过半径表示数值,更容易区分数值差异

相似图表

玉珏图
玉珏图
比较类

分类

占比类