说实话,我第一次接触 ECharts 的时候,整个人是懵的。文档看了一半,代码抄了一半,结果屏幕上一片空白,连个报错信息都不给,那种挫败感简直让人想砸键盘。但当你真正跨过那些坑之后,你会发现 ECharts 其实是个脾气很好的“画家”——只要你给对了画布和指令,它就能给你画出惊艳的效果。
作为过来人,我想把这条路上所有的坑、所有的弯路,甚至是我半夜排查出来的那些奇葩 bug,都掰开了揉碎了讲给你听。这不是一篇教科书,这是我踩过的雷,你不需要再踩一遍。
第一章:别急着写代码,先搞定“地基”
很多新手一上来就想 npm install echarts,然后复制粘贴官网的 demo,结果运行报错,或者图表出不来。这时候千万别慌,90% 的问题出在“地基”没打牢。
1.1 安装方式:选对适合你的那条路
ECharts 支持多种引入方式,不同的项目场景选择不同。如果你是完全零基础,我建议你从最简单的 CDN 引入开始,哪怕你用的是 React、Vue 或者原生 HTML。
方法一:CDN 引入(新手首选,最快看到效果)
打开你的 index.html,在 </body> 标签前加上这两行:
<!-- 引入 ECharts 主文件 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
注意版本号,尽量锁定一个稳定的版本(比如 5.4.3),避免后续因为自动更新导致 API 变化而出错。
方法二:npm 安装(适合 Vue/React 项目)
npm install echarts --save
# 或者如果你用的是 yarn
yarn add echarts
然后在你的组件中引入:
import * as echarts from 'echarts';
// 注意:ECharts v5 推荐用 * as echarts,而不是直接 import echarts
1.2 致命错误:容器必须有高度!
这是新手最常见、最容易被忽视的坑。ECharts 的容器(div)必须有明确的宽度和高度,否则图表画不出来,而且不会报错!
想象一下,你让一个画家在一个看不见的画布上画画,他当然画不出来,对吧?
错误示范:
<div id="chart" style="width: 100%;"></div>
<script>
var chart = echarts.init(document.getElementById('chart'));
chart.setOption({ /* ...配置项 */ });
</script>
上面这个代码,div 只有宽度,没有高度,图表绝对不会显示。
正确做法:
<div id="chart" style="width: 100%; height: 400px;"></div>
或者,如果你希望图表自适应容器高度,确保父容器有明确的高度:
.container {
height: 500px;
}
#chart {
width: 100%;
height: 100%;
}
第二章:初始化图表——别再把 echarts.init 写乱了
初始化是创建图表的第一步。很多教程直接给你一段代码,但你不知道为什么要这么写。我来带你拆解一下。
2.1 基本初始化流程
// 1. 获取 DOM 元素
var dom = document.getElementById('chart');
// 2. 初始化 ECharts 实例
var myChart = echarts.init(dom);
// 3. 配置选项
var option = {
title: {
text: '我的第一个 ECharts 图表'
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70],
type: 'line'
}]
};
// 4. 使用配置项显示图表
myChart.setOption(option);
关键点解析:
echarts.init(dom):这一步是创建图表实例。记住,一个 DOM 元素只能对应一个 ECharts 实例。如果你重复初始化同一个 DOM,可能会导致内存泄漏或者显示异常。setOption(option):这一步是把配置“告诉”图表。你可以多次调用setOption来更新图表,但要注意,第二次调用时,如果不传notMerge: true,ECharts 会尝试合并配置,这有时会导致意想不到的结果。
2.2 避坑:响应式自适应
很多开发者发现,当浏览器窗口大小改变时,图表不会自动调整大小。这是因为 ECharts 不会自动监听窗口变化。你需要手动处理。
解决方案:
// 监听窗口大小变化
window.addEventListener('resize', function() {
myChart.resize();
});
或者,如果你使用的是 Vue 或 React,最好在组件的 mounted 或 useEffect 中绑定 resize 事件,并在组件卸载时移除,避免内存泄漏。
Vue 示例:
mounted() {
this.myChart = echarts.init(this.$refs.chart);
window.addEventListener('resize', this.handleResize);
},
beforeUnmount() {
window.removeEventListener('resize', this.handleResize);
this.myChart.dispose(); // 销毁实例,释放内存
},
methods: {
handleResize() {
this.myChart.resize();
}
}
第三章:配置项——ECharts 的“灵魂”
ECharts 的强大之处在于其丰富的配置项。配置项大致可以分为几大类:标题、提示框、图例、工具箱、数据集、坐标轴、系列、图形元素等。
3.1 标题(title)
标题是图表的“名字”,让用户一眼就知道图表在展示什么。
title: {
text: '2023年销售额统计', // 主标题
subtext: '数据来源:财务部', // 副标题
left: 'center', // 水平位置:left, center, right
top: '5%', // 垂直位置:百分比或像素
textStyle: {
fontSize: 20,
color: '#333'
}
}
技巧: 如果图表有很多系列,建议把标题放在上方居中,这样布局更清晰。
3.2 提示框(tooltip)
当用户鼠标悬停在数据点上时,显示详细信息的浮层。这是用户交互的关键部分。
tooltip: {
trigger: 'axis', // 触发方式:'item'(数据点)或 'axis'(坐标轴)
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderColor: '#ccc',
textStyle: {
color: '#333'
},
formatter: function(params) {
// params 是当前悬停数据点的信息数组
return params[0].name + '<br/>' +
params[0].seriesName + ':' + params[0].value + ' 万元';
}
}
注意: trigger: 'axis' 适合折线图、柱状图等,表示当鼠标在某个坐标轴位置时,显示该轴上所有数据点的信息。trigger: 'item' 适合饼图等,表示当鼠标悬停在某个具体图形上时显示信息。
3.3 图例(legend)
图例用于展示不同系列的名称和颜色,用户可以点击图例来显示或隐藏某个系列。
legend: {
data: ['销售额', '利润'], // 与 series 中的 name 对应
top: '10%',
right: '5%'
}
3.4 坐标轴(xAxis, yAxis)
坐标轴是图表的“骨架”。ECharts 支持多种坐标轴类型:'category'(类目轴)、'value'(数值轴)、'time'(时间轴)、'log'(对数轴)等。
类目轴(category)示例:
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五'],
axisLabel: {
rotate: 45 // 如果标签太长,可以旋转显示
}
}
数值轴(value)示例:
yAxis: {
type: 'value',
min: 0,
max: 500,
axisLabel: {
formatter: '{value} 万元' // 自定义标签格式
}
}
3.5 系列(series)
系列是图表的“血肉”,定义图表展示什么数据、用什么图形。
series: [
{
name: '销售额',
type: 'line',
data: [120, 200, 150, 80, 70],
smooth: true, // 平滑曲线
areaStyle: {
opacity: 0.3 // 填充区域透明度
}
},
{
name: '利润',
type: 'bar',
data: [30, 50, 40, 20, 15],
itemStyle: {
color: '#5470c6'
}
}
]
常见图形类型:
'bar':柱状图'line':折线图'pie':饼图'scatter':散点图'effectScatter':涟漪散点图'radar':雷达图'heatmap':热力图'map':地图'tree':树图'treemap':矩形树图'sunburst':旭日图'boxplot':箱线图'candlestick':K线图'chart':流图'funnel':漏斗图'gauge':仪表盘
第四章:常见报错及解决方案
4.1 报错:Cannot read properties of undefined (reading 'init')
原因: 你忘记引入 ECharts 库,或者引入顺序不对。
解决: 确保在调用 echarts.init 之前,ECharts 脚本已经加载完成。
<!-- 确保在 init 之前加载 -->
<script src="echarts.min.js"></script>
<script>
var myChart = echarts.init(document.getElementById('chart'));
</script>
4.2 报错:canvas is empty 或 Cannot read property 'getContext' of null
原因: 你试图初始化的 DOM 元素不存在,或者 ID 写错了。
解决: 检查 HTML 中是否有对应的 id,并且确保脚本在 DOM 加载完成后执行。
<!-- 确保 DOM 存在 -->
<div id="chart" style="width: 600px; height: 400px;"></div>
<script>
// 确保在 DOM 加载后执行
window.onload = function() {
var chartDom = document.getElementById('chart');
var myChart = echarts.init(chartDom);
};
</script>
4.3 图表不显示,也没有报错
原因: 容器高度为 0。这是最常见的问题!
解决: 给容器设置明确的高度。
<div id="chart" style="width: 100%; height: 400px;"></div>
4.4 数据更新了,但图表没变化
原因: 你没有调用 setOption,或者 setOption 的参数不对。
解决: 在数据更新后,重新调用 setOption。
// 假设 newData 是你更新后的数据
myChart.setOption({
series: [{
data: newData
}]
});
注意: 如果你只想更新数据,而不改变其他配置,可以使用 notMerge: false(默认值),ECharts 会尝试合并配置。但如果你发现配置混乱,可以尝试 notMerge: true。
第五章:进阶技巧——让你的图表更专业
5.1 使用数据集(dataset)简化配置
当你的数据格式比较复杂时,使用 dataset 可以让配置更简洁。
option = {
dataset: {
source: [
['product', '2023', '2024'],
['衬衫', 120, 150],
['羊毛衫', 200, 230],
['雨衣', 50, 80]
]
},
xAxis: { type: 'category' },
series: [
{ type: 'bar', encode: { x: 0, y: 1 } },
{ type: 'bar', encode: { x: 0, y: 2 } }
]
};
5.2 自定义主题
ECharts 支持自定义主题,你可以使用在线工具(如 ECharts Theme Builder)生成 JSON 主题,然后导入。
echarts.registerTheme('myTheme', {
// 主题配置 JSON
});
myChart.setOption(option, { theme: 'myTheme' });
5.3 性能优化
当数据量很大时(比如上万条),图表可能会卡顿。
解决方案:
- 使用
large: true启用大数据量优化模式(仅适用于折线图、散点图等)。 - 使用
sampling: 'lttb'对数据进行采样。 - 避免在
setOption中频繁创建大量对象。
series: [{
type: 'line',
data: largeData,
large: true,
sampling: 'lttb'
}]
第六章:实战案例——做一个完整的销售仪表盘
让我们把前面学到的知识整合起来,做一个简单的销售仪表盘。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>销售仪表盘</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
.container { display: flex; gap: 20px; }
.chart-box { width: calc(50% - 10px); height: 400px; border: 1px solid #ddd; padding: 10px; }
</style>
</head>
<body>
<h1>2023年销售仪表盘</h1>
<div class="container">
<div id="lineChart" class="chart-box"></div>
<div id="pieChart" class="chart-box"></div>
</div>
<script>
// 折线图:月度销售额
var lineChart = echarts.init(document.getElementById('lineChart'));
var lineOption = {
title: { text: '月度销售额趋势' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: ['1月', '2月', '3月', '4月', '5月', '6月'] },
yAxis: { type: 'value', name: '销售额(万元)' },
series: [{
data: [120, 200, 150, 80, 70, 130],
type: 'line',
smooth: true,
areaStyle: { opacity: 0.3 }
}]
};
lineChart.setOption(lineOption);
// 饼图:各品类销售占比
var pieChart = echarts.init(document.getElementById('pieChart'));
var pieOption = {
title: { text: '品类销售占比' },
tooltip: { trigger: 'item' },
legend: { top: 'bottom' },
series: [{
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: { show: false, position: 'center' },
emphasis: {
label: { show: true, fontSize: 20, fontWeight: 'bold' }
},
data: [
{ value: 1048, name: '电子产品' },
{ value: 735, name: '服装' },
{ value: 580, name: '食品' },
{ value: 484, name: '家居' },
{ value: 300, name: '其他' }
]
}]
};
pieChart.setOption(pieOption);
// 响应式处理
window.addEventListener('resize', function() {
lineChart.resize();
pieChart.resize();
});
</script>
</body>
</html>
第七章:学习资源与社区
- 官方文档: https://echarts.apache.org/ —— 最权威的资料,例子丰富。
- 示例库: https://echarts.apache.org/examples/ —— 直接复制示例代码,修改数据
