引言
ECharts 是一个由百度开源、现由 Apache 基金会维护的、功能强大的 JavaScript 图表库。它提供了丰富的图表类型(折线图、柱状图、饼图、散点图、地图等),以及高度的可定制性,使得开发者能够轻松创建交互式、可视化的数据展示。对于零基础的学习者来说,ECharts 的学习曲线相对平缓,但要系统地掌握并应用到实际项目中,需要一个清晰的学习路径。本文将为你提供一个从零开始,逐步深入,最终能够独立完成实战项目的完整学习指南。
第一部分:基础准备与环境搭建
1.1 必备知识储备
在开始学习 ECharts 之前,你需要具备一些基础的前端知识:
- HTML/CSS:了解如何创建网页结构和基本样式。
- JavaScript:掌握基本的语法、变量、函数、数组、对象等概念。ES6+ 的语法(如
let/const、箭头函数、模板字符串)会很有帮助。 - DOM 操作:了解如何通过 JavaScript 操作 HTML 元素。
示例:如果你连 document.getElementById 都不熟悉,建议先花时间巩固 JavaScript 基础。
1.2 开发环境搭建
你不需要复杂的开发环境,一个简单的 HTML 文件和浏览器即可开始。
- 创建项目文件夹:在你的电脑上创建一个文件夹,例如
echarts-learning。 - 创建 HTML 文件:在文件夹中创建一个
index.html文件。 - 引入 ECharts:你可以通过 CDN(内容分发网络)快速引入 ECharts,无需下载。
- 访问 ECharts 官网 或 CDN 网站(如 jsDelivr)获取最新的 CDN 链接。
- 在
index.html中引入 ECharts 的 JS 文件。
代码示例:index.html 的基础结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ECharts 入门示例</title>
<!-- 引入 ECharts 核心文件 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
/* 设置图表容器的大小 */
#main {
width: 600px;
height: 400px;
border: 1px solid #ccc;
margin: 20px auto;
}
</style>
</head>
<body>
<!-- 准备一个具备大小(宽高)的Dom -->
<div id="main"></div>
<script>
// JavaScript 代码将写在这里
</script>
</body>
</html>
第二部分:核心概念与基础图表绘制
2.1 ECharts 的核心概念
理解 ECharts 的几个核心概念是绘制图表的基础:
- 实例 (Instance):每个 ECharts 图表都是一个实例,通过
echarts.init()方法创建。 - 配置项 (Option):一个 JavaScript 对象,描述了图表的所有样式和数据。这是 ECharts 的核心,通过修改
option对象来改变图表。 - DOM 容器:一个 HTML 元素(通常是
div),用于承载图表。必须设置明确的宽度和高度。
2.2 绘制第一个图表:折线图
让我们以最简单的折线图为例,完成从 0 到 1 的突破。
步骤:
- 获取 DOM 容器。
- 初始化 ECharts 实例。
- 定义配置项
option。 - 将
option设置给实例。
代码示例:在 index.html 的 <script> 标签内添加以下代码
// 1. 获取 DOM 容器
const chartDom = document.getElementById('main');
// 2. 初始化 ECharts 实例
const myChart = echarts.init(chartDom);
// 3. 定义配置项 option
const option = {
// 标题
title: {
text: '简单折线图',
left: 'center'
},
// 提示框组件
tooltip: {
trigger: 'axis'
},
// X 轴
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
// Y 轴
yAxis: {
type: 'value'
},
// 系列(数据)
series: [
{
name: '销量',
type: 'line', // 图表类型:折线图
data: [150, 230, 224, 218, 135, 147, 260],
smooth: true // 平滑曲线
}
]
};
// 4. 将 option 设置给实例
myChart.setOption(option);
// 可选:监听窗口大小变化,使图表自适应
window.addEventListener('resize', function() {
myChart.resize();
});
解释:
title:设置图表标题。tooltip:鼠标悬停时显示的提示信息。xAxis和yAxis:定义坐标轴,type: 'category'表示类目轴(如星期),type: 'value'表示数值轴。series:数据系列,type: 'line'指定为折线图,data是具体的数据数组。smooth: true:让折线变得平滑。
2.3 常用图表类型
ECharts 支持多种图表,以下是几种最常用的:
- 柱状图 (Bar):
type: 'bar',用于比较不同类别的数值大小。 - 饼图 (Pie):
type: 'pie',用于显示部分与整体的比例关系。 - 散点图 (Scatter):
type: 'scatter',用于展示两个变量之间的关系。 - 地图 (Map):
type: 'map',用于展示地理区域数据(需要额外引入地图数据)。
柱状图示例:只需将折线图的 series 中的 type 改为 'bar',并调整 xAxis 和 yAxis 的配置即可。
// 在 option 中修改 series
series: [
{
name: '销量',
type: 'bar', // 改为柱状图
data: [150, 230, 224, 218, 135, 147, 260],
// 可以添加柱状图特有的配置,如柱子宽度
barWidth: '50%'
}
]
第三部分:深入学习配置项
3.1 全局配置项
全局配置项影响整个图表的外观和行为。
color:调色板,用于设置系列的颜色。backgroundColor:图表背景色。textStyle:全局文本样式。animation:动画相关配置。
示例:设置自定义颜色和背景
const option = {
backgroundColor: '#f5f5f5', // 浅灰色背景
color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'], // 自定义颜色数组
// ... 其他配置项
};
3.2 组件配置项
ECharts 图表由多个组件构成,每个组件都可以单独配置。
title:标题组件。legend:图例组件,用于标识系列。tooltip:提示框组件,非常常用。grid:直角坐标系内绘图网格,用于调整图表区域的位置和大小。axis:坐标轴(xAxis,yAxis)。series:数据系列。
示例:配置图例和提示框
const option = {
// ... 其他配置
legend: {
data: ['销量', '利润'], // 图例名称,需要与 series 中的 name 对应
top: 'bottom' // 图例位置:底部
},
tooltip: {
trigger: 'axis', // 触发类型:坐标轴触发
axisPointer: {
type: 'cross' // 指示器类型:十字准星
},
formatter: function(params) {
// 自定义提示框内容
let result = params[0].name + '<br/>';
params.forEach(item => {
result += `${item.marker} ${item.seriesName}: ${item.value}<br/>`;
});
return result;
}
},
// ... series 配置
};
3.3 数据系列 (Series) 配置
series 是 ECharts 的核心,它定义了数据和图表类型。每个系列可以有不同的类型。
多系列图表示例:同时显示销量和利润的折线图
const option = {
// ... title, legend, xAxis, yAxis 配置
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月']
},
yAxis: {
type: 'value'
},
series: [
{
name: '销量',
type: 'line',
data: [100, 120, 150, 180, 200, 220],
smooth: true
},
{
name: '利润',
type: 'line',
data: [20, 30, 45, 60, 80, 100],
smooth: true,
yAxisIndex: 0 // 使用同一个 Y 轴,如果数据范围差异大,可以使用第二个 Y 轴 (yAxisIndex: 1)
}
]
};
第四部分:数据处理与动态更新
4.1 数据格式
ECharts 支持多种数据格式,最常见的是数组格式。对于复杂数据,可以使用对象数组。
对象数组示例:使用 data 中的 value 属性
// 数据格式:对象数组
const data = [
{ value: 150, name: '周一' },
{ value: 230, name: '周二' },
{ value: 224, name: '周三' }
];
// 在 series 中使用
series: [{
type: 'pie',
data: data // 直接使用对象数组
}]
4.2 动态更新数据
在实际应用中,数据往往是动态的(如从 API 获取)。ECharts 提供了 setOption 方法来更新图表。
关键点:
setOption可以多次调用,每次调用都会合并新的配置项。- 如果要完全替换配置,可以使用
setOption(option, true),其中第二个参数notMerge设为true。
示例:模拟从 API 获取数据并更新图表
// 假设这是你的图表实例
const myChart = echarts.init(document.getElementById('main'));
// 初始配置
const initialOption = {
title: { text: '实时销量' },
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value' },
series: [{ type: 'line', data: [] }]
};
myChart.setOption(initialOption);
// 模拟获取数据的函数
function fetchData() {
// 在实际项目中,这里会是 fetch 或 axios 请求
return new Promise((resolve) => {
setTimeout(() => {
// 模拟返回的数据
const newData = {
categories: ['1月', '2月', '3月', '4月', '5月', '6月'],
values: [100, 120, 150, 180, 200, 220]
};
resolve(newData);
}, 1000);
});
}
// 更新图表的函数
function updateChart() {
fetchData().then(data => {
const newOption = {
xAxis: {
data: data.categories
},
series: [{
data: data.values
}]
};
// 更新图表,不合并配置(因为只更新部分)
myChart.setOption(newOption);
});
}
// 每隔 3 秒更新一次数据
setInterval(updateChart, 3000);
4.3 响应式图表
为了让图表在窗口大小变化时自动调整,需要监听 resize 事件。
代码示例:
// 在初始化图表后添加
window.addEventListener('resize', function() {
myChart.resize();
});
优化:如果页面中有多个图表,可以使用一个函数来管理所有图表的 resize。
// 管理多个图表
const chartInstances = [];
function addChart(chart) {
chartInstances.push(chart);
}
function resizeAllCharts() {
chartInstances.forEach(chart => chart.resize());
}
window.addEventListener('resize', resizeAllCharts);
// 使用
const chart1 = echarts.init(document.getElementById('chart1'));
const chart2 = echarts.init(document.getElementById('chart2'));
addChart(chart1);
addChart(chart2);
第五部分:进阶技巧与高级图表
5.1 自定义样式
ECharts 允许深度自定义样式,包括颜色、字体、边框等。
示例:自定义柱状图样式
series: [{
type: 'bar',
data: [120, 200, 150, 80, 70, 110, 130],
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
]), // 渐变色
borderRadius: [5, 5, 0, 0] // 圆角
},
label: {
show: true,
position: 'top',
formatter: '{c}' // 显示数值
}
}]
5.2 地图图表
地图是 ECharts 的一大特色。使用地图需要先注册地图数据。
步骤:
- 从 ECharts 官网 下载地图 JSON 文件(如
china.json)。 - 使用
echarts.registerMap注册地图。 - 在
series中使用type: 'map'。
示例:中国地图
// 假设你已经下载了 china.json 并加载到变量 chinaJson 中
// 在实际项目中,你可以通过 fetch 获取
fetch('path/to/china.json')
.then(response => response.json())
.then(chinaJson => {
// 注册地图
echarts.registerMap('china', chinaJson);
const chartDom = document.getElementById('main');
const myChart = echarts.init(chartDom);
const option = {
title: {
text: '中国地图示例',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{b}<br/>{c} (万人)'
},
visualMap: {
min: 800,
max: 50000,
text: ['高', '低'],
realtime: false,
calculable: true,
inRange: {
color: ['#50a3ba', '#eac736', '#d94e5d']
}
},
series: [
{
name: '中国',
type: 'map',
map: 'china', // 使用注册的地图名称
roam: true, // 开启鼠标缩放和平移
label: {
show: true
},
data: [
{ name: '北京', value: 2154 },
{ name: '天津', value: 1294 },
{ name: '上海', value: 2424 },
// ... 其他省份数据
]
}
]
};
myChart.setOption(option);
});
5.3 交互与事件监听
ECharts 支持丰富的交互事件,如点击、悬停等。
常用事件:
click:点击图表元素。mouseover:鼠标悬停。mouseout:鼠标移出。dataZoom:数据区域缩放。
示例:监听点击事件
// 监听点击事件
myChart.on('click', function(params) {
// params 包含点击的系列、数据、名称等信息
console.log('点击了:', params.name, '值为:', params.value);
// 可以在这里执行跳转、弹窗等操作
alert(`你点击了 ${params.name},值为 ${params.value}`);
});
// 监听数据区域缩放事件
myChart.on('dataZoom', function(params) {
console.log('数据缩放了', params);
// 可以根据缩放后的数据范围重新请求数据
});
第六部分:实战项目:销售数据仪表盘
6.1 项目需求分析
我们来构建一个简单的销售数据仪表盘,包含以下图表:
- 月度销售额折线图:展示近 12 个月的销售额趋势。
- 产品类别占比饼图:展示不同产品类别的销售额占比。
- 地区销售柱状图:展示各地区的销售额对比。
- 实时数据更新:模拟实时数据更新。
6.2 项目结构
创建以下文件:
index.html:主页面。style.css:样式文件。script.js:主要的 JavaScript 代码。
6.3 代码实现
index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>销售数据仪表盘</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<div class="dashboard">
<h1>销售数据仪表盘</h1>
<div class="chart-container">
<div id="lineChart" class="chart"></div>
<div id="pieChart" class="chart"></div>
<div id="barChart" class="chart"></div>
</div>
<div class="controls">
<button id="updateBtn">更新数据</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
style.css
body {
font-family: Arial, sans-serif;
background-color: #f0f2f5;
margin: 0;
padding: 20px;
}
.dashboard {
max-width: 1200px;
margin: 0 auto;
}
h1 {
text-align: center;
color: #333;
}
.chart-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-top: 20px;
}
.chart {
height: 350px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
padding: 10px;
}
/* 让饼图单独占一行 */
#pieChart {
grid-column: 1 / -1;
}
.controls {
text-align: center;
margin-top: 20px;
}
button {
padding: 10px 20px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #40a9ff;
}
script.js
// 模拟数据生成函数
function generateData() {
const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
const sales = months.map(() => Math.floor(Math.random() * 5000) + 1000);
const categories = ['电子产品', '服装', '家居', '食品'];
const categorySales = categories.map(() => Math.floor(Math.random() * 3000) + 500);
const regions = ['华东', '华南', '华北', '西南', '东北'];
const regionSales = regions.map(() => Math.floor(Math.random() * 4000) + 800);
return { months, sales, categories, categorySales, regions, regionSales };
}
// 初始化图表
function initCharts() {
const lineChart = echarts.init(document.getElementById('lineChart'));
const pieChart = echarts.init(document.getElementById('pieChart'));
const barChart = echarts.init(document.getElementById('barChart'));
// 初始数据
const data = generateData();
// 月度销售额折线图配置
const lineOption = {
title: { text: '月度销售额趋势', left: 'center' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: data.months },
yAxis: { type: 'value', name: '销售额(元)' },
series: [{
name: '销售额',
type: 'line',
data: data.sales,
smooth: true,
areaStyle: { opacity: 0.3 } // 区域填充
}]
};
// 产品类别占比饼图配置
const pieOption = {
title: { text: '产品类别占比', left: 'center' },
tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
series: [{
name: '类别',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: '{b}: {d}%'
},
data: data.categories.map((cat, idx) => ({
name: cat,
value: data.categorySales[idx]
}))
}]
};
// 地区销售柱状图配置
const barOption = {
title: { text: '地区销售额对比', left: 'center' },
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
xAxis: { type: 'category', data: data.regions },
yAxis: { type: 'value', name: '销售额(元)' },
series: [{
name: '销售额',
type: 'bar',
data: data.regionSales,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
},
label: {
show: true,
position: 'top'
}
}]
};
// 设置初始配置
lineChart.setOption(lineOption);
pieChart.setOption(pieOption);
barChart.setOption(barOption);
// 返回图表实例,用于后续更新
return { lineChart, pieChart, barChart };
}
// 更新图表数据
function updateCharts(charts) {
const newData = generateData();
// 更新折线图
charts.lineChart.setOption({
xAxis: { data: newData.months },
series: [{ data: newData.sales }]
});
// 更新饼图
charts.pieChart.setOption({
series: [{
data: newData.categories.map((cat, idx) => ({
name: cat,
value: newData.categorySales[idx]
}))
}]
});
// 更新柱状图
charts.barChart.setOption({
xAxis: { data: newData.regions },
series: [{ data: newData.regionSales }]
});
}
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
const charts = initCharts();
// 监听窗口大小变化
window.addEventListener('resize', function() {
charts.lineChart.resize();
charts.pieChart.resize();
charts.barChart.resize();
});
// 监听按钮点击事件
document.getElementById('updateBtn').addEventListener('click', function() {
updateCharts(charts);
});
// 模拟实时数据更新(每5秒自动更新一次)
setInterval(() => {
updateCharts(charts);
}, 5000);
});
6.4 项目总结
通过这个实战项目,你学习了:
- 如何在一个页面中集成多个图表。
- 如何使用 CSS Grid 布局来组织图表。
- 如何模拟数据并动态更新图表。
- 如何添加交互按钮和定时更新。
- 如何管理多个图表实例的
resize事件。
第七部分:最佳实践与常见问题
7.1 性能优化
- 大数据量渲染:当数据点超过 10,000 时,考虑使用
large: true或largeThreshold配置项。 - 按需引入:如果只使用部分图表类型,可以按需引入 ECharts 模块以减小包体积。
- 避免频繁更新:使用
requestAnimationFrame或防抖函数来优化高频更新。
7.2 常见问题与解决方案
图表不显示:
- 检查 DOM 容器是否有明确的宽度和高度。
- 检查
setOption是否被调用。 - 检查浏览器控制台是否有错误。
数据更新后图表未刷新:
- 确保
setOption被调用。 - 如果是部分更新,确保
notMerge参数设置正确(默认为false,即合并配置)。
- 确保
图表在移动端显示异常:
- 使用
media配置项来响应式调整配置。 - 确保容器宽度使用百分比或
vw单位。
- 使用
示例:使用 media 配置响应式
const option = {
// 基础配置
title: { text: '响应式图表' },
// ... 其他配置
media: [
{
query: { maxWidth: 768 }, // 当屏幕宽度小于等于 768px
option: {
title: { text: '移动端标题' },
legend: { show: false }, // 隐藏图例
series: [{ label: { show: false } }] // 隐藏标签
}
}
]
};
7.3 扩展学习资源
- 官方文档:ECharts 官网 是最好的学习资源,包含详细的配置项说明和示例。
- 示例库:ECharts 示例 提供了大量可直接运行的示例代码。
- 社区:GitHub 上的 ECharts 仓库、Stack Overflow、CSDN 等社区都有丰富的讨论和问题解答。
- 书籍与课程:可以搜索相关的在线课程或书籍,系统学习。
结语
ECharts 是一个强大且灵活的图表库,即使零基础也能通过系统的学习路径快速上手。从环境搭建、基础图表绘制,到深入配置、动态更新,再到实战项目,每一步都至关重要。记住,实践是最好的老师,多动手写代码、多尝试不同的配置项,你会越来越熟练。希望这份指南能帮助你顺利开启 ECharts 的学习之旅,并在实际项目中创造出优秀的数据可视化作品。祝你学习愉快!
