### ECharts 入门教程

Tecvan · 更新于 2020-10-29

# ECharts 饼图

## 2. 实例解说

### 2.1 简单饼图

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>

<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));

var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
series: [
{
type: 'pie',
data: [
{ value: 820, name: 'Mon' },
{ value: 932, name: 'Tue' },
{ value: 901, name: 'Wed' },
{ value: 934, name: 'Thu' },
{ value: 1290, name: 'Fri' },
{ value: 1330, name: 'Sat' },
{ value: 1320, name: 'Sun' },
],
label: {
show: true,
position: 'inside',
},
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
``````

``````{
"data": [820, 932, 901, 934, 1290, 1330, 1320]
}
``````

### 2.2 饼图半径

• `number`: 指定饼图半径的像素尺寸
• `string`: 接受百分比值如 `20%`，指定饼图半径相对整个画布的比例
• `array`: 接受二维数组如 `[30, '50%']`，第一项指定内圆半径，第二项指定外圆半径

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>

<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));

var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
series: [
{
type: 'pie',
data: [
{ value: 820, name: 'Mon' },
{ value: 932, name: 'Tue' },
{ value: 901, name: 'Wed' },
{ value: 934, name: 'Thu' },
{ value: 1290, name: 'Fri' },
{ value: 1330, name: 'Sat' },
{ value: 1320, name: 'Sun' },
],
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
``````

### 2.3 嵌套饼图

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>

<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var cats = [
{ name: '水果', children: ['苹果', '雪梨', '橙子', '香蕉'] },
{ name: '蔬菜', children: ['津白', '紫甘蓝', '苦瓜', '菜心'] },
{ name: '水产', children: ['虎皮虾', '青蟹', '鲈鱼', '大闸蟹'] },
{ name: '干杂', children: ['红豆', '东北大米', '陈皮', '党参'] },
];
// 生成随机数据
// 不必关注
function generateData(cats) {
var MAX = 100,
MIN = 50;
var len = cats.length;
var result = { inner: [], outer: [] };
for (let i = 0; i < len; i++) {
var cat = cats[i];
var vector = [];
for (let j = 0; j < cat.children.length; j++) {
var num = Math.round(Math.random() * (MAX - MIN) + MIN);
vector.push({ name: cat.children[j], value: num });
}
var total = vector.reduce((r, v) => r + v.value, 0);
result.inner.push({ name: cat.name, value: total });
result.outer = result.outer.concat(vector);
}
return result;
}

var myChart = echarts.init(document.getElementById('main'));
var data = generateData(cats);

var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
series: [
{ type: 'pie', data: data.inner, radius: '40%', label: { position: 'inside' } },
{ type: 'pie', data: data.outer, radius: ['50%', '80%'] },
],
};
myChart.setOption(option);
</script>
</body>
</html>
``````

### 2.4 饼图选中效果

selectedMode boolean|string false 选中模式，表示是否支持扇区选中效果
selectedOffset number 10 选中扇区的偏移距离

`selectedMode` 属性支持：

• `false`: 默认值，关闭选中效果
• `'single'`: 支持选定单个扇区
• `'multiple'`: 支持选定多个扇区

2.3 嵌套饼图 基础上，只需修改配置项：

``````{
"selectedMode": "single"
}
``````

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>

<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var cats = [
{ name: '水果', children: ['苹果', '雪梨', '橙子', '香蕉'] },
{ name: '蔬菜', children: ['津白', '紫甘蓝', '苦瓜', '菜心'] },
{ name: '水产', children: ['虎皮虾', '青蟹', '鲈鱼', '大闸蟹'] },
{ name: '干杂', children: ['红豆', '东北大米', '陈皮', '党参'] },
];
// 生成随机数据
// 不必关注
function generateData(cats) {
var MAX = 100,
MIN = 50;
var len = cats.length;
var result = { inner: [], outer: [] };
for (let i = 0; i < len; i++) {
var cat = cats[i];
var vector = [];
for (let j = 0; j < cat.children.length; j++) {
var num = Math.round(Math.random() * (MAX - MIN) + MIN);
vector.push({ name: cat.children[j], value: num });
}
var total = vector.reduce((r, v) => r + v.value, 0);
result.inner.push({ name: cat.name, value: total });
result.outer = result.outer.concat(vector);
}
return result;
}

var myChart = echarts.init(document.getElementById('main'));
var data = generateData(cats);

var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
series: [
{
type: 'pie',
data: data.inner,
label: { position: 'inside' },
id: 'inner',
selectedMode: 'multiple',
},
{ type: 'pie', id: 'outer', data: data.outer, radius: ['50%', '80%'], selectedMode: 'multiple' },
],
};
myChart.setOption(option);

// 找到关联类别
function lookup(e) {
// 当前操作的项
var currentItem = e.name;
var isSelected = e.selected[e.name];
// 当前操作的序列
var seriesId = e.seriesId;
if (seriesId === 'inner') {
// 内层饼图选中时，子项同步选中
var currentCat = cats.find(function (cat) {
return cat.name === currentItem;
});
return { seriesIndex: 1, names: currentCat.children, isSelected: isSelected };
} else {
// 外层饼图选中时，父类同步选中
var parentCat = cats.find(function (cat) {
return (
cat.children.findIndex(function (subItem) {
return subItem === currentItem;
}) >= 0
);
});
for (var i = 0; i < parentCat.children.length; i++) {
var subItem = parentCat.children[i];
if (e.selected[subItem] === true) {
return { seriesIndex: 0, names: [parentCat.name], isSelected: true };
}
}
return { seriesIndex: 0, names: [parentCat.name], isSelected: false };
}
}

myChart.on('pieselectchanged', function (e) {
var target = lookup(e);
var names = target.names;
var isSelected = target.isSelected;
var seriesIndex = target.seriesIndex;
for (var i = 0; i < names.length; i++) {
// 发出选中动作
myChart.dispatchAction({
type: isSelected ? 'pieSelect' : 'pieUnSelect',
seriesIndex: seriesIndex,
name: names[i],
});
}
});
</script>
</body>
</html>
``````

### 2.5 南丁格尔玫瑰图

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>

<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var cats = [
{ name: '水果', children: ['苹果', '雪梨', '橙子', '香蕉'] },
{ name: '蔬菜', children: ['津白', '紫甘蓝', '苦瓜', '菜心'] },
{ name: '水产', children: ['虎皮虾', '青蟹', '鲈鱼', '大闸蟹'] },
{ name: '干杂', children: ['红豆', '东北大米', '陈皮', '党参'] },
];
// 生成随机数据
// 不必关注
function generateData(cats) {
var MAX = 100,
MIN = 0;
var len = cats.length;
var result = { inner: [], outer: [] };
for (let i = 0; i < len; i++) {
var cat = cats[i];
var vector = [];
for (let j = 0; j < cat.children.length; j++) {
var num = Math.round(Math.random() * (MAX - MIN) + MIN);
vector.push({ name: cat.children[j], value: num });
}
var total = vector.reduce((r, v) => r + v.value, 0);
result.inner.push({ name: cat.name, value: total });
result.outer = result.outer.concat(vector);
}
return result;
}

var myChart = echarts.init(document.getElementById('main'));
var data = generateData(cats);

var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
series: [
{ type: 'pie', data: data.inner, radius: '40%', label: { position: 'inside' } },
],
};
myChart.setOption(option);
</script>
</body>
</html>
``````

`roseType` 支持如下属性：

• `false`: 默认值，不开启玫瑰图效果，此时各扇区半径相同
• `'radius'`: 扇区圆心角展现数据的百分比，半径展现数据的大小
• `'area'`: 所有扇区圆心角相同，仅通过半径展现数据大小

### 2.6 标签优化

• `inside`/`inner`: 标签显示在饼图扇区内部
• `outside`: 标签显示在饼图扇区外部，通过视觉引导线连接扇区
• `center`: 标签显示在饼图的圆心点

`label.position` 基础上，我们来看看标签在不同位置上的优化。

## 3. 标签自动隐藏

`label.position = inner` 时，扇区的标签在扇区内部渲染。每个扇区的大小依据数据值而定，考虑某数值在序列中占比很小时，分配到的角度也会很小，可能导致标签展示不全，考虑如下数值序列：

``````{
"type": "pie",
"label": { "position": "inside" },
"data": [
{ "value": 20, "name": "Mon" },
{ "value": 932, "name": "Tue" },
{ "value": 901, "name": "Wed" },
{ "value": 934, "name": "Thu" },
{ "value": 1290, "name": "Fri" },
{ "value": 1330, "name": "Sat" },
{ "value": 1320, "name": "Sun" }
]
}
``````

``````{
"type": "pie",
"label": { "position": "inside" },
"minShowLabelAngle": 10,
"data": [
{ "value": 20, "name": "Mon" },
{ "value": 932, "name": "Tue" },
{ "value": 901, "name": "Wed" },
{ "value": 934, "name": "Thu" },
{ "value": 1290, "name": "Fri" },
{ "value": 1330, "name": "Sat" },
{ "value": 1320, "name": "Sun" }
]
}
``````

## 4. 视觉引导线配置

`label.position = outside` 时，扇区的标签将在扇区外部渲染并通过视觉引导线连接到相应的扇区区域。可通过 `labelLine` 项修改引导线效果，接受如下子项：

show boolean true 是否显示引导线
length number 视觉引导线第一段的长度。
length2 number 视觉引导线第二段的长度。
smooth boolean|number true 是否平滑视觉引导线，默认不平滑，可以设置成 `true` 平滑显示，也可以设置为 0 到 1 的值，表示平滑程度。
lineStyle object TODO: 增加链接，线段样式

``````<!DOCTYPE html>
<html lang="zh-CN">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: { feature: { saveAsImage: {} } },
series: [
{
type: 'pie',
data: [
{ value: 20, name: 'Mon' },
{ value: 932, name: 'Tue' },
{ value: 901, name: 'Wed' },
{ value: 934, name: 'Thu' },
{ value: 1290, name: 'Fri' },
{ value: 1330, name: 'Sat' },
{ value: 1320, name: 'Sun' },
],
label: { show: true, position: 'outside' },
labelLine: { length: 30, length2: 40 },
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
``````