如何用ECharts轻松制作专业饼图并解决常见数据可视化难题

引言
在数据可视化领域,饼图(Pie Chart)是一种经典且直观的图表类型,常用于展示各部分在整体中的占比关系。ECharts作为一款功能强大的开源JavaScript图表库,提供了丰富的配置选项和交互功能,能够帮助开发者轻松创建专业级的饼图。然而,在实际应用中,我们常常会遇到数据标签重叠、颜色搭配不当、动态数据更新等难题。本文将详细介绍如何使用ECharts制作专业饼图,并针对常见问题提供解决方案。
一、ECharts基础介绍
1.1 ECharts简介
ECharts是由百度开源的一个使用JavaScript实现的图表库,可以流畅地运行在PC和移动设备上。它支持多种图表类型,包括折线图、柱状图、饼图、散点图等,并且具有丰富的交互功能。
1.2 引入ECharts
在使用ECharts之前,需要先引入ECharts库。可以通过CDN方式引入,也可以下载到本地引入。


1.3 基本使用步骤
准备一个具备宽高的DOM容器
初始化ECharts实例
指定图表的配置项和数据
将配置项设置给ECharts实例




ECharts饼图示例







二、制作专业饼图的进阶技巧
2.1 环形饼图(Donut Chart)
环形饼图是饼图的变体,中间留有空白区域,可以放置其他信息(如总计值)。
var option = {
title: {
text: ‘环形饼图示例’,
left: ‘center’
},
tooltip: {
trigger: ‘item’,
formatter: ‘{b}: {c} ({d}%)’
},
legend: {
orient: ‘vertical’,
left: ‘left’
},
series: [
{
name: ‘访问来源’,
type: ‘pie’,
radius: [‘40%’, ‘70%’], // 内半径和外半径
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10, // 扇形圆角
borderColor: ‘#fff’,
borderWidth: 2
},
label: {
show: true,
position: ‘outside’ // 标签位置
},
emphasis: {
label: {
show: true,
fontSize: 16,
fontWeight: ‘bold’
}
},
labelLine: {
show: true,
length: 15,
length2: 10
},
data: [
{value: 1048, name: ‘搜索引擎’},
{value: 735, name: ‘直接访问’},
{value: 580, name: ‘邮件营销’},
{value: 484, name: ‘联盟广告’},
{value: 300, name: ‘视频广告’}
]
}
]
};
2.2 南丁格尔玫瑰图(Rose Chart)
南丁格尔玫瑰图是一种特殊的饼图,通过扇形半径的变化来展示数据大小,比普通饼图更能突出差异。
var option = {
title: {
text: ‘南丁格尔玫瑰图示例’,
left: ‘center’
},
tooltip: {
trigger: ‘item’,
formatter: ‘{a}
{b} : {c} ({d}%)’
},
legend: {
data: [‘产品A’, ‘产品B’, ‘产品C’, ‘产品D’, ‘产品E’],
bottom: 0
},
series: [
{
name: ‘销售额’,
type: ‘pie’,
radius: [20, 100], // 半径范围
center: [‘50%’, ‘50%’],
roseType: ‘area’, // 南丁格尔玫瑰图类型
itemStyle: {
borderRadius: 5
},
label: {
show: false
},
emphasis: {
label: {
show: true
}
},
data: [
{value: 10, name: ‘产品A’},
{value: 5, name: ‘产品B’},
{value: 15, name: ‘产品C’},
{value: 25, name: ‘产品D’},
{value: 20, name: ‘产品E’}
]
}
]
};
2.3 嵌套饼图(Nested Pie Chart)
嵌套饼图可以在一个图表中展示多层数据,适合展示分类和子分类的关系。
var option = {
title: {
text: ‘嵌套饼图示例’,
left: ‘center’
},
tooltip: {
trigger: ‘item’,
formatter: ‘{a}
{b} : {c} ({d}%)’
},
legend: {
data: [‘产品大类’, ‘产品小类’],
top: ‘bottom’
},
series: [
{
name: ‘产品大类’,
type: ‘pie’,
radius: [0, ‘30%’],
label: {
position: ‘inner’
},
labelLine: {
show: false
},
itemStyle: {
borderRadius: 5,
borderColor: ‘#fff’,
borderWidth: 2
},
data: [
{value: 1000, name: ‘电子产品’},
{value: 800, name: ‘家居用品’},
{value: 600, name: ‘服装鞋帽’}
]
},
{
name: ‘产品小类’,
type: ‘pie’,
radius: [‘40%’, ‘70%’],
label: {
alignTo: ‘edge’,
margin: 20
},
labelLine: {
length: 15,
length2: 10
},
itemStyle: {
borderRadius: 5,
borderColor: ‘#fff’,
borderWidth: 2
},
data: [
{value: 400, name: ‘手机’},
{value: 300, name: ‘电脑’},
{value: 300, name: ‘平板’},
{value: 200, name: ‘电视’},
{value: 200, name: ‘冰箱’},
{value: 200, name: ‘洗衣机’},
{value: 200, name: ‘空调’},
{value: 200, name: ‘衬衫’},
{value: 200, name: ‘裤子’},
{value: 200, name: ‘鞋子’}
]
}
]
};
三、解决常见数据可视化难题
3.1 数据标签重叠问题
当饼图扇形较多或数据值相近时,标签容易重叠,影响可读性。
解决方案1:调整标签位置和显示策略
var option = {
series: [
{
type: ‘pie’,
data: […],
label: {
show: true,
position: ‘outside’, // 标签显示在扇形外部
formatter: ‘{b}\n{c}’, // 格式化标签内容
fontSize: 12,
lineHeight: 14
},
labelLine: {
show: true,
length: 15, // 第一段引导线长度
length2: 10, // 第二段引导线长度
smooth: true, // 平滑曲线
lineStyle: {
width: 1,
type: ‘solid’
}
},
// 使用avoidLabelOverlap避免重叠
avoidLabelOverlap: true
}
]
};
解决方案2:使用图例代替部分标签
var option = {
legend: {
type: ‘scroll’, // 可滚动图例
orient: ‘vertical’,
right: 10,
top: 20,
bottom: 20,
data: [‘产品A’, ‘产品B’, ‘产品C’, ‘产品D’, ‘产品E’, ‘产品F’, ‘产品G’, ‘产品H’]
},
series: [
{
type: ‘pie’,
data: […],
label: {
show: false // 隐藏标签,通过图例展示
}
}
]
};
解决方案3:动态调整标签显示
// 根据数据值动态调整标签显示
function getLabelOption(data) {
const total = data.reduce((sum, item) => sum + item.value, 0);
return {
label: {
show: function(params) {
// 只显示占比大于5%的标签
return params.value / total > 0.05;
},
position: ‘outside’,
formatter: ‘{b}: {d}%’
}
};
}

var option = {
series: [
{
type: ‘pie’,
data: data,
…getLabelOption(data)
}
]
};
3.2 颜色搭配不当问题
不合理的颜色选择会影响图表的美观性和可读性。
解决方案1:使用ECharts内置配色方案
var option = {
color: [‘#5470c6’, ‘#91cc75’, ‘#fac858’, ‘#ee6666’, ‘#73c0de’, ‘#3ba272’, ‘#fc8452’, ‘#9a60b4’, ‘#ea7ccc’]
};
解决方案2:使用渐变色增强视觉效果
var option = {
series: [
{
type: ‘pie’,
data: […],
itemStyle: {
color: function(params) {
// 创建渐变色
const colorList = [
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: ‘#667eea’ },
{ offset: 1, color: ‘#764ba2’ }
]),
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: ‘#f093fb’ },
{ offset: 1, color: ‘#f5576c’ }
]),
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: ‘#4facfe’ },
{ offset: 1, color: ‘#00f2fe’ }
])
];
return colorList[params.dataIndex % colorList.length];
}
}
}
]
};
解决方案3:使用色盲友好配色
// 色盲友好配色方案(适合红绿色盲)
var colorBlindFriendlyColors = [
‘#0072B2’, // 蓝色
‘#E69F00’, // 橙色
‘#56B4E9’, // 浅蓝
‘#009E73’, // 蓝绿色
‘#F0E442’, // 黄色
‘#D55E00’, // 红橙色
‘#CC79A7’ // 紫红色
];

var option = {
color: colorBlindFriendlyColors
};
3.3 动态数据更新问题
在实际应用中,数据经常需要实时更新或动态变化。
解决方案1:使用ECharts的setOption方法更新数据
// 初始化图表
var myChart = echarts.init(document.getElementById(‘main’));

// 初始数据
var initialData = [
{value: 1048, name: ‘产品A’},
{value: 735, name: ‘产品B’},
{value: 580, name: ‘产品C’}
];

// 更新数据函数
function updateChart(newData) {
var option = {
series: [{
type: ‘pie’,
data: newData
}]
};
myChart.setOption(option);
}

// 模拟数据更新(实际应用中可能来自API)
setInterval(() => {
// 生成随机新数据
var newData = initialData.map(item => ({
…item,
value: Math.floor(Math.random() * 1000) + 100
}));
updateChart(newData);
}, 3000);
解决方案2:使用ECharts的动画效果
var option = {
series: [
{
type: ‘pie’,
data: […],
animationDuration: 1000, // 动画时长
animationEasing: ‘cubicOut’, // 动画缓动
animationDelay: function(idx) {
return idx * 100; // 每个扇形的动画延迟
}
}
]
};
解决方案3:使用ECharts的resize事件处理
// 监听窗口大小变化,自动调整图表大小
window.addEventListener(‘resize’, function() {
myChart.resize();
});

// 或者使用防抖函数优化性能
function debounce(func, wait) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}

window.addEventListener(‘resize’, debounce(() => {
myChart.resize();
}, 200));
3.4 大数据量展示问题
当数据项过多时,饼图会变得拥挤,难以阅读。
解决方案1:数据聚合
// 将小数据项合并为”其他”
function aggregateData(data, threshold = 0.05) {
const total = data.reduce((sum, item) => sum + item.value, 0);
const aggregated = [];
const others = [];

data.forEach(item => {
if (item.value / total >= threshold) {
aggregated.push(item);
} else {
others.push(item);
}
});

if (others.length > 0) {
const otherValue = others.reduce((sum, item) => sum + item.value, 0);
aggregated.push({
value: otherValue,
name: ‘其他’,
itemStyle: {
color: ‘#ccc’ // 用灰色表示其他
}
});
}

return aggregated;
}

// 使用示例
var rawData = [
{value: 100, name: ‘A’},
{value: 80, name: ‘B’},
{value: 60, name: ‘C’},
{value: 40, name: ‘D’},
{value: 30, name: ‘E’},
{value: 20, name: ‘F’},
{value: 15, name: ‘G’},
{value: 10, name: ‘H’},
{value: 5, name: ‘I’}
];

var aggregatedData = aggregateData(rawData, 0.1); // 阈值设为10%

var option = {
series: [{
type: ‘pie’,
data: aggregatedData
}]
};
解决方案2:使用饼图+表格组合展示


名称 数值 占比


3.5 交互功能增强
ECharts提供了丰富的交互功能,可以增强用户体验。
解决方案1:点击扇形高亮显示
var option = {
series: [
{
type: ‘pie’,
data: […],
selectedMode: ‘single’, // 单选模式
select: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: ‘rgba(0, 0, 0, 0.5)’
}
}
}
]
};

// 监听点击事件
myChart.on(‘click’, function(params) {
console.log(‘点击了:’, params.name, ‘值:’, params.value);
// 可以在这里添加自定义逻辑,如显示详细信息
});
解决方案2:悬停显示详细信息
var option = {
tooltip: {
trigger: ‘item’,
formatter: function(params) {
// 自定义提示框内容
return `

${params.name}
数值: ${params.value}
占比: ${params.percent}%

`;
},
backgroundColor: ‘rgba(50, 50, 50, 0.9)’,
borderColor: ‘#333’,
borderWidth: 1,
textStyle: {
color: ‘#fff’
},
padding: 10
}
};
解决方案3:添加图例点击交互
var option = {
legend: {
type: ‘scroll’,
orient: ‘vertical’,
right: 10,
top: 20,
bottom: 20,
data: [‘产品A’, ‘产品B’, ‘产品C’, ‘产品D’, ‘产品E’],
selected: { // 默认选中状态
‘产品A’: true,
‘产品B’: true,
‘产品C’: true,
‘产品D’: false,
‘产品E’: false
}
},
series: [
{
type: ‘pie’,
data: […],
// 图例点击时的回调
legendHoverLink: true
}
]
};

// 监听图例点击事件
myChart.on(‘legendselectchanged’, function(params) {
console.log(‘图例选择改变:’, params.selected);
// 可以在这里添加自定义逻辑
});
四、完整示例:销售数据可视化系统
下面是一个完整的销售数据可视化系统示例,整合了前面介绍的各种技巧:




销售数据可视化系统


销售数据可视化系统

使用ECharts制作专业饼图并解决常见数据可视化难题





产品类别 销售额 占比 同比增长




五、最佳实践与性能优化
5.1 性能优化技巧
数据量控制
:饼图扇形数量建议不超过20个,过多时考虑数据聚合
动画优化
:在大数据量时关闭动画或减少动画时长
懒加载
:对于非首屏图表,可以延迟初始化
防抖处理
:对resize事件使用防抖函数
5.2 可访问性考虑
颜色对比度
:确保颜色对比度符合WCAG标准
键盘导航
:为交互元素添加键盘支持
屏幕阅读器
:使用ARIA属性增强可访问性
色盲友好
:避免仅依赖颜色传递信息
5.3 响应式设计
// 响应式配置
function getResponsiveOption() {
const width = window.innerWidth;
let radius, labelPosition;

if (width < 768) { radius = ['30%', '60%']; labelPosition = 'inside'; } else { radius = ['40%', '70%']; labelPosition = 'outside'; } return { series: [{ type: 'pie', radius: radius, label: { position: labelPosition } }] }; } // 监听窗口大小变化 window.addEventListener('resize', function() { myChart.setOption(getResponsiveOption()); }); 六、总结 通过本文的介绍,我们学习了如何使用ECharts制作专业饼图,并解决了数据标签重叠、颜色搭配、动态更新、大数据量展示等常见问题。ECharts提供了丰富的配置选项和交互功能,能够满足各种数据可视化需求。 关键要点回顾: 基础配置 :掌握ECharts的基本使用方法和饼图配置 进阶技巧 :学习环形饼图、南丁格尔玫瑰图、嵌套饼图等变体 问题解决 :针对常见难题提供具体解决方案 完整示例 :通过销售数据可视化系统展示实际应用 最佳实践 :性能优化、可访问性、响应式设计等 在实际项目中,建议根据具体需求选择合适的饼图类型和配置,并始终考虑用户体验和数据可读性。ECharts的灵活性和强大功能使其成为数据可视化的优秀选择。 七、扩展资源 ECharts官方文档 : https://echarts.apache.org/zh/index.html ECharts示例库 : https://echarts.apache.org/examples/zh/index.html 数据可视化原则 :《The Visual Display of Quantitative Information》- Edward Tufte 配色工具 :Adobe Color, Coolors, ColorBrewer 性能优化指南 :ECharts性能优化最佳实践 通过不断实践和探索,你将能够制作出更加专业和美观的数据可视化图表,有效传达数据背后的故事。