引言:为什么选择ECharts?
在当今数据驱动的时代,数据可视化已成为将复杂数据转化为直观洞察的关键工具。ECharts(Enterprise Charts)是由百度开源的一个功能强大、使用广泛的JavaScript图表库。它凭借其丰富的图表类型、流畅的交互体验、高度的可定制性以及良好的兼容性,已成为前端开发者的首选可视化工具之一。无论是简单的柱状图、饼图,还是复杂的地理坐标系、3D图表,ECharts都能轻松应对。本指南将从零开始,系统性地带你掌握ECharts的核心技能,并通过实战案例展示其应用,帮助你快速成为数据可视化领域的专家。
第一部分:ECharts基础入门
1.1 ECharts简介与安装
ECharts是一个基于JavaScript的图表库,它不依赖任何外部库(如jQuery),可以直接在浏览器中运行。ECharts支持Canvas和SVG两种渲染模式,其中Canvas模式性能更优,适合大数据量渲染;SVG模式则更适合需要高保真度的场景。
安装ECharts: 有多种方式可以引入ECharts,最常用的是通过CDN链接或npm安装。
CDN方式(适用于快速原型开发或静态页面):
<!-- 引入ECharts核心库 --> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>npm方式(适用于现代前端框架项目,如Vue、React):
npm install echarts --save然后在项目中引入: “`javascript // ES6模块化引入 import * as echarts from ‘echarts’; // 或者按需引入(减少打包体积) import { init, use } from ‘echarts/core’; import { BarChart, LineChart } from ‘echarts/charts’; import { TitleComponent, TooltipComponent, GridComponent } from ‘echarts/components’; import { CanvasRenderer } from ‘echarts/renderers’;
use([
BarChart,
LineChart,
TitleComponent,
TooltipComponent,
GridComponent,
CanvasRenderer
]);
### 1.2 第一个ECharts图表:Hello World
让我们创建一个最简单的柱状图,展示ECharts的基本使用流程。
**步骤**:
1. 准备一个DOM容器。
2. 初始化ECharts实例。
3. 设置图表配置项(Option)。
4. 将配置项设置到实例中。
**代码示例**:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我的第一个ECharts图表</title>
<!-- 引入ECharts -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<!-- 1. 准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 2. 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 3. 指定图表的配置项和数据
var option = {
title: {
text: '简单柱状图示例'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar', // 指定图表类型为柱状图
data: [5, 20, 36, 10, 10, 20]
}]
};
// 4. 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
代码解析:
echarts.init(dom): 初始化一个ECharts实例,需要传入一个DOM元素。option对象:这是ECharts的核心,所有图表的配置都在这里。它是一个JavaScript对象,包含标题、提示框、图例、坐标轴、系列等组件。series: 系列列表,每个系列对应一种图表类型和一组数据。type: 'bar'表示柱状图,data是具体的数据值。
1.3 ECharts核心概念:Option配置项详解
ECharts的配置项(Option)是一个树形结构,主要包含以下部分:
- title: 标题组件,可以设置标题、副标题、位置、样式等。
- legend: 图例组件,用于展示系列名称,可以控制系列的显示与隐藏。
- tooltip: 提示框组件,当鼠标悬停在图表上时显示的提示信息。
- grid: 直角坐标系的网格,用于调整图表在容器中的位置和大小。
- xAxis / yAxis: 直角坐标系的横轴和纵轴,可以设置坐标轴类型(类目、数值、时间等)、刻度、标签等。
- series: 系列列表,每个系列代表一组数据和一种图表类型。常见的类型有:
line: 折线图bar: 柱状图pie: 饼图scatter: 散点图map: 地图radar: 雷达图k: K线图heatmap: 热力图graph: 关系图tree: 树图treemap: 矩形树图funnel: 漏斗图gauge: 仪表盘candlestick: K线图(与k类型相同)boxplot: 箱形图parallel: 平行坐标系sankey: 桑基图themeRiver: 主题河流图calendar: 日历图custom: 自定义系列
- color: 全局调色盘,用于设置系列的颜色。
- backgroundColor: 图表背景色。
- textStyle: 全局文本样式。
一个更复杂的Option示例:
var option = {
backgroundColor: '#f9f9f9',
title: {
text: '某公司产品季度销量',
subtext: '数据来自虚构',
left: 'center',
textStyle: {
fontSize: 18,
color: '#333'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
legend: {
data: ['产品A', '产品B', '产品C'],
top: 40
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Q1', 'Q2', 'Q3', 'Q4']
},
yAxis: {
type: 'value',
name: '销量(万件)'
},
series: [
{
name: '产品A',
type: 'line',
smooth: true,
data: [120, 132, 101, 134],
itemStyle: {
color: '#5470c6'
}
},
{
name: '产品B',
type: 'line',
smooth: true,
data: [220, 182, 191, 234],
itemStyle: {
color: '#91cc75'
}
},
{
name: '产品C',
type: 'line',
smooth: true,
data: [150, 230, 224, 180],
itemStyle: {
color: '#fac858'
}
}
]
};
1.4 响应式与自适应
在实际应用中,图表需要适应不同屏幕尺寸。ECharts提供了resize方法来实现自适应。
代码示例:
// 初始化图表
var myChart = echarts.init(document.getElementById('main'));
// 监听窗口大小变化,调用resize方法
window.addEventListener('resize', function() {
myChart.resize();
});
// 如果使用Vue/React等框架,可以在组件挂载和销毁时处理
// Vue示例:
export default {
mounted() {
this.initChart();
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
},
methods: {
handleResize() {
if (this.myChart) {
this.myChart.resize();
}
}
}
}
第二部分:ECharts核心图表类型详解与实战
2.1 柱状图与条形图
柱状图用于比较不同类别的数据,条形图是柱状图的横向版本。
实战:堆叠柱状图 堆叠柱状图用于展示每个类别下不同子类别的总和。
var option = {
title: {
text: '某公司各部门季度费用',
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow' // 默认为'line',这里改为'shadow'以显示阴影
}
},
legend: {
data: ['人力成本', '办公费用', '差旅费用'],
top: 30
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['研发部', '市场部', '销售部', '行政部']
},
yAxis: {
type: 'value',
name: '费用(万元)'
},
series: [
{
name: '人力成本',
type: 'bar',
stack: 'total', // 堆叠标识,相同stack值的系列会堆叠在一起
emphasis: {
focus: 'series'
},
data: [320, 302, 301, 334]
},
{
name: '办公费用',
type: 'bar',
stack: 'total',
data: [120, 132, 101, 134]
},
{
name: '差旅费用',
type: 'bar',
stack: 'total',
data: [220, 182, 191, 234]
}
]
};
2.2 折线图与面积图
折线图用于展示数据随时间或类别的变化趋势,面积图是折线图的填充版本。
实战:多系列折线图与标记点
var option = {
title: {
text: '某网站用户访问量',
left: 'center'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['PC端', '移动端', '平板端'],
top: 30
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
yAxis: {
type: 'value',
name: '访问量(万次)'
},
series: [
{
name: 'PC端',
type: 'line',
smooth: true, // 平滑曲线
data: [820, 932, 901, 934, 1290, 1330, 1320],
markPoint: {
data: [
{ type: 'max', name: '最大值' },
{ type: 'min', name: '最小值' }
]
},
markLine: {
data: [
{ type: 'average', name: '平均值' }
]
}
},
{
name: '移动端',
type: 'line',
smooth: true,
data: [620, 732, 701, 734, 1090, 1130, 1120]
},
{
name: '平板端',
type: 'line',
smooth: true,
data: [420, 532, 501, 534, 890, 930, 920]
}
]
};
2.3 饼图与环形图
饼图用于展示各部分占总体的比例,环形图是饼图的中间挖空版本。
实战:带引导线的饼图
var option = {
title: {
text: '某地区人口构成',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)' // a: 系列名, b: 数据名, c: 数值, d: 百分比
},
legend: {
orient: 'vertical',
left: 'left',
data: ['汉族', '少数民族', '其他']
},
series: [
{
name: '人口构成',
type: 'pie',
radius: ['40%', '70%'], // 设置内半径和外半径,形成环形图
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10, // 圆角
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
position: 'outside', // 标签位置
formatter: '{b}: {c} ({d}%)' // 标签格式
},
emphasis: {
label: {
show: true,
fontSize: 16,
fontWeight: 'bold'
}
},
labelLine: {
show: true,
length: 15, // 引导线第一段长度
length2: 10 // 引导线第二段长度
},
data: [
{ value: 1048, name: '汉族' },
{ value: 335, name: '少数民族' },
{ value: 580, name: '其他' }
]
}
]
};
2.4 散点图
散点图用于展示两个变量之间的关系,常用于发现数据中的模式和异常值。
实战:气泡图(带第三维度)
var option = {
title: {
text: '身高与体重关系(气泡图)',
left: 'center'
},
tooltip: {
formatter: function (params) {
return `姓名: ${params.data[2]}<br/>身高: ${params.data[0]}cm<br/>体重: ${params.data[1]}kg<br/>年龄: ${params.data[3]}岁`;
}
},
xAxis: {
name: '身高 (cm)',
scale: true
},
yAxis: {
name: '体重 (kg)',
scale: true
},
series: [{
type: 'scatter',
symbolSize: function (data) {
// 根据年龄调整气泡大小
return data[3] / 2; // 假设年龄在20-60之间,气泡大小在10-30之间
},
data: [
[170, 65, '张三', 25],
[175, 70, '李四', 30],
[165, 55, '王五', 22],
[180, 80, '赵六', 45],
[160, 50, '钱七', 28],
[185, 85, '孙八', 50],
[172, 68, '周九', 35],
[168, 62, '吴十', 40]
],
itemStyle: {
color: function(params) {
// 根据年龄设置颜色
var age = params.data[3];
if (age < 30) return '#5470c6';
else if (age < 40) return '#91cc75';
else return '#fac858';
}
}
}]
};
2.5 地图
ECharts支持丰富的地图类型,包括世界地图、中国地图以及各省市地图。需要引入相应的地图JSON数据。
实战:中国地图热力图
// 1. 首先需要引入中国地图的JSON数据(通常从ECharts官网下载或使用第三方库)
// 假设我们已经通过以下方式引入了中国地图数据:
// <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/map/js/china.js"></script>
var option = {
title: {
text: '中国各省份GDP热力图',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{b}<br/>GDP: {c} 万亿元'
},
visualMap: {
min: 0,
max: 12,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
}
},
series: [
{
name: '中国各省份GDP',
type: 'map',
map: 'china', // 使用中国地图
roam: true, // 支持拖拽和缩放
label: {
show: true,
fontSize: 10
},
emphasis: {
label: {
show: true
},
itemStyle: {
areaColor: '#a50026'
}
},
data: [
{name: '北京', value: 3.6},
{name: '天津', value: 1.4},
{name: '上海', value: 3.8},
{name: '重庆', value: 2.5},
{name: '河北', value: 3.6},
{name: '山西', value: 1.8},
{name: '辽宁', value: 2.5},
{name: '吉林', value: 1.3},
{name: '黑龙江', value: 1.4},
{name: '江苏', value: 10.3},
{name: '浙江', value: 6.5},
{name: '安徽', value: 3.9},
{name: '福建', value: 4.4},
{name: '江西', value: 2.6},
{name: '山东', value: 7.3},
{name: '河南', value: 5.5},
{name: '湖北', value: 4.6},
{name: '湖南', value: 4.2},
{name: '广东', value: 11.0},
{name: '海南', value: 0.6},
{name: '四川', value: 4.9},
{name: '贵州', value: 1.8},
{name: '云南', value: 2.3},
{name: '陕西', value: 2.6},
{name: '甘肃', value: 0.9},
{name: '青海', value: 0.3},
{name: '台湾', value: 4.2},
{name: '内蒙古', value: 1.7},
{name: '广西', value: 2.2},
{name: '西藏', value: 0.2},
{name: '宁夏', value: 0.4},
{name: '新疆', value: 1.4},
{name: '香港', value: 2.4},
{name: '澳门', value: 0.2}
]
}
]
};
2.6 其他高级图表类型简介
- 雷达图:用于展示多维度数据,常用于能力评估、产品对比。
- K线图:用于展示股票、期货等金融数据,包含开盘价、收盘价、最高价、最低价。
- 热力图:用于展示二维数据的分布,常用于时间序列数据(如小时-星期)。
- 关系图:用于展示节点和边的关系,常用于社交网络、知识图谱。
- 桑基图:用于展示流量、能量的转移和分布,常用于能源、资金流向分析。
- 仪表盘:用于展示单个指标的完成度,常用于KPI监控。
第三部分:ECharts高级功能与交互
3.1 动态数据与异步加载
ECharts可以轻松处理动态数据,通过setOption方法更新图表。
实战:实时更新柱状图
// 假设我们有一个定时器,每2秒从服务器获取新数据
var myChart = echarts.init(document.getElementById('main'));
var option = {
title: { text: '实时数据监控' },
xAxis: { type: 'category', data: ['A', 'B', 'C', 'D'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [0, 0, 0, 0] }]
};
myChart.setOption(option);
// 模拟从服务器获取数据
function fetchData() {
// 在实际项目中,这里可能是AJAX请求
return new Promise(resolve => {
setTimeout(() => {
const newData = [
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100)
];
resolve(newData);
}, 1000);
});
}
// 定时更新
setInterval(async () => {
const data = await fetchData();
myChart.setOption({
series: [{
data: data
}]
});
}, 2000);
3.2 交互事件
ECharts提供了丰富的交互事件,如点击、鼠标悬停等,可以绑定回调函数。
实战:点击柱状图获取数据
var myChart = echarts.init(document.getElementById('main'));
var option = {
title: { text: '点击柱状图获取数据' },
xAxis: { type: 'category', data: ['产品A', '产品B', '产品C', '产品D'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [120, 200, 150, 80] }]
};
myChart.setOption(option);
// 绑定点击事件
myChart.on('click', function(params) {
// params 包含点击的系列信息、数据索引、数据值等
console.log('点击了:', params.name);
console.log('数值:', params.value);
console.log('系列名称:', params.seriesName);
console.log('完整数据:', params.data);
// 可以在这里弹出提示框或跳转页面
alert(`你点击了${params.name},数值为${params.value}`);
});
3.3 图表联动
通过事件监听,可以实现多个图表之间的联动。
实战:两个图表联动
<div id="chart1" style="width: 400px; height: 300px; float: left;"></div>
<div id="chart2" style="width: 400px; height: 300px; float: left; margin-left: 20px;"></div>
<script>
// 初始化两个图表
var chart1 = echarts.init(document.getElementById('chart1'));
var chart2 = echarts.init(document.getElementById('chart2'));
// 设置第一个图表(柱状图)
chart1.setOption({
title: { text: '产品销量' },
xAxis: { type: 'category', data: ['A', 'B', 'C', 'D'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [120, 200, 150, 80] }]
});
// 设置第二个图表(饼图)
chart2.setOption({
title: { text: '产品占比' },
series: [{
type: 'pie',
radius: '60%',
data: [
{ value: 120, name: 'A' },
{ value: 200, name: 'B' },
{ value: 150, name: 'C' },
{ value: 80, name: 'D' }
]
}]
});
// 联动:点击柱状图,饼图高亮对应扇区
chart1.on('click', function(params) {
// 获取饼图的当前选中状态
var pieData = chart2.getOption().series[0].data;
var index = pieData.findIndex(item => item.name === params.name);
// 触发饼图的高亮和取消高亮
chart2.dispatchAction({
type: 'downplay',
seriesIndex: 0
});
chart2.dispatchAction({
type: 'highlight',
seriesIndex: 0,
dataIndex: index
});
});
</script>
3.4 自定义系列与渲染
ECharts允许通过custom系列类型进行高度自定义的绘制,使用Canvas API进行绘制。
实战:自定义绘制一个简单的形状
var myChart = echarts.init(document.getElementById('main'));
// 自定义系列配置
var option = {
title: { text: '自定义系列示例' },
xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五'] },
yAxis: { type: 'value' },
series: [{
type: 'custom',
renderItem: function(params, api) {
// params: 包含系列索引、数据索引等
// api: 提供坐标转换、获取数据等方法
var xValue = api.value(0); // 获取x轴数据(类别)
var yValue = api.value(1); // 获取y轴数据(数值)
// 获取坐标点
var point = api.coord([xValue, yValue]);
// 自定义绘制一个三角形
var height = 20; // 三角形高度
var width = 20; // 三角形宽度
return {
type: 'polygon',
shape: {
points: [
[point[0], point[1]], // 顶点
[point[0] - width/2, point[1] + height], // 左下
[point[0] + width/2, point[1] + height] // 右下
]
},
style: api.style({
fill: '#5470c6',
stroke: '#000'
})
};
},
data: [100, 150, 120, 180, 200]
}]
};
myChart.setOption(option);
第四部分:ECharts与前端框架集成
4.1 在Vue中使用ECharts
安装与引入:
npm install echarts --save
封装为Vue组件:
<template>
<div ref="chartContainer" style="width: 100%; height: 400px;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'EChart',
props: {
option: {
type: Object,
required: true
}
},
data() {
return {
chartInstance: null
};
},
mounted() {
this.initChart();
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
if (this.chartInstance) {
this.chartInstance.dispose();
this.chartInstance = null;
}
window.removeEventListener('resize', this.handleResize);
},
watch: {
option: {
deep: true,
handler(newVal) {
if (this.chartInstance) {
this.chartInstance.setOption(newVal);
}
}
}
},
methods: {
initChart() {
const container = this.$refs.chartContainer;
if (container) {
this.chartInstance = echarts.init(container);
this.chartInstance.setOption(this.option);
}
},
handleResize() {
if (this.chartInstance) {
this.chartInstance.resize();
}
}
}
};
</script>
使用组件:
<template>
<div>
<EChart :option="chartOption" />
</div>
</template>
<script>
import EChart from './components/EChart.vue';
export default {
components: { EChart },
data() {
return {
chartOption: {
title: { text: 'Vue中的ECharts' },
xAxis: { type: 'category', data: ['A', 'B', 'C'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [100, 200, 150] }]
}
};
}
};
</script>
4.2 在React中使用ECharts
安装与引入:
npm install echarts --save
封装为React组件:
import React, { useEffect, useRef, useState } from 'react';
import * as echarts from 'echarts';
const EChart = ({ option }) => {
const chartRef = useRef(null);
const chartInstance = useRef(null);
useEffect(() => {
if (chartRef.current) {
chartInstance.current = echarts.init(chartRef.current);
chartInstance.current.setOption(option);
}
const handleResize = () => {
if (chartInstance.current) {
chartInstance.current.resize();
}
};
window.addEventListener('resize', handleResize);
return () => {
if (chartInstance.current) {
chartInstance.current.dispose();
}
window.removeEventListener('resize', handleResize);
};
}, [option]);
return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />;
};
export default EChart;
使用组件:
import React, { useState } from 'react';
import EChart from './components/EChart';
function App() {
const [chartOption] = useState({
title: { text: 'React中的ECharts' },
xAxis: { type: 'category', data: ['A', 'B', 'C'] },
yAxis: { type: 'value' },
series: [{ type: 'bar', data: [100, 200, 150] }]
});
return (
<div className="App">
<EChart option={chartOption} />
</div>
);
}
export default App;
第五部分:性能优化与最佳实践
5.1 性能优化技巧
按需引入:只引入需要的图表类型和组件,减少打包体积。
// 按需引入示例 import { init, use } from 'echarts/core'; import { BarChart, LineChart } from 'echarts/charts'; import { TitleComponent, TooltipComponent, GridComponent } from 'echarts/components'; import { CanvasRenderer } from 'echarts/renderers'; use([ BarChart, LineChart, TitleComponent, TooltipComponent, GridComponent, CanvasRenderer ]);大数据量优化:
- 使用
large: true开启大数据量优化模式(适用于散点图、折线图)。 - 使用
progressive渐进式渲染。 - 对于极大数据量,考虑使用WebGL渲染(ECharts GL)。
- 使用
避免频繁更新:
- 使用
throttle或debounce函数控制setOption的调用频率。 - 对于实时数据,可以合并多次更新。
- 使用
内存管理:
- 在组件销毁时调用
chartInstance.dispose()释放内存。 - 避免在循环中重复创建ECharts实例。
- 在组件销毁时调用
5.2 常见问题与解决方案
问题1:图表不显示或显示不全
- 原因:DOM容器没有设置宽高,或宽高为0。
- 解决:确保容器有明确的宽高(如
width: 600px; height: 400px;)。
问题2:图表在Tab切换或隐藏后显示异常
- 原因:图表在隐藏时无法正确计算尺寸。
- 解决:在显示时调用
chartInstance.resize()。
问题3:中文显示为方框
- 原因:浏览器缺少中文字体或ECharts字体配置问题。
- 解决:在
textStyle中指定字体,或确保页面有中文字体。
问题4:地图数据缺失
- 原因:未正确引入地图JSON数据。
- 解决:确保引入了对应的地图数据文件(如
china.js)。
第六部分:实战项目:销售数据仪表盘
6.1 项目需求分析
我们需要创建一个销售数据仪表盘,包含以下图表:
- 月度销售趋势图(折线图)
- 产品类别占比(饼图)
- 各地区销售对比(柱状图)
- 实时销售监控(动态更新)
6.2 项目结构
sales-dashboard/
├── index.html
├── css/
│ └── style.css
├── js/
│ └── main.js
└── data/
└── mock-data.js
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="css/style.css">
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<div class="dashboard">
<header class="header">
<h1>销售数据仪表盘</h1>
<div class="time" id="currentTime"></div>
</header>
<div class="charts-container">
<div class="chart-box">
<div id="trendChart" class="chart"></div>
</div>
<div class="chart-box">
<div id="pieChart" class="chart"></div>
</div>
<div class="chart-box">
<div id="barChart" class="chart"></div>
</div>
<div class="chart-box">
<div id="realTimeChart" class="chart"></div>
</div>
</div>
</div>
<script src="js/main.js"></script>
</body>
</html>
css/style.css:
body {
margin: 0;
padding: 0;
font-family: 'Microsoft YaHei', sans-serif;
background-color: #f5f5f5;
}
.dashboard {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background-color: #2c3e50;
color: white;
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
margin: 0;
font-size: 24px;
}
.time {
font-size: 16px;
}
.charts-container {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 15px;
padding: 15px;
}
.chart-box {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 15px;
display: flex;
flex-direction: column;
}
.chart {
flex: 1;
min-height: 250px;
}
js/main.js:
// 模拟数据
const mockData = {
months: ['1月', '2月', '3月', '4月', '5月', '6月'],
salesTrend: [120, 132, 101, 134, 90, 230],
productCategories: [
{ value: 1048, name: '电子产品' },
{ value: 735, name: '服装' },
{ value: 580, name: '食品' },
{ value: 484, name: '家居' }
],
regions: ['华北', '华东', '华南', '华中', '西南', '西北', '东北'],
regionSales: [320, 450, 380, 290, 250, 180, 150]
};
// 初始化图表
function initCharts() {
// 1. 月度销售趋势图
const trendChart = echarts.init(document.getElementById('trendChart'));
const trendOption = {
title: { text: '月度销售趋势', left: 'center' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: mockData.months },
yAxis: { type: 'value', name: '销售额(万元)' },
series: [{
type: 'line',
data: mockData.salesTrend,
smooth: true,
areaStyle: { opacity: 0.3 },
itemStyle: { color: '#5470c6' }
}]
};
trendChart.setOption(trendOption);
// 2. 产品类别占比
const pieChart = echarts.init(document.getElementById('pieChart'));
const pieOption = {
title: { text: '产品类别占比', left: 'center' },
tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
legend: { orient: 'vertical', left: 'left' },
series: [{
type: 'pie',
radius: ['40%', '70%'],
data: mockData.productCategories,
itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 }
}]
};
pieChart.setOption(pieOption);
// 3. 各地区销售对比
const barChart = echarts.init(document.getElementById('barChart'));
const barOption = {
title: { text: '各地区销售对比', left: 'center' },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: mockData.regions, axisLabel: { rotate: 30 } },
yAxis: { type: 'value', name: '销售额(万元)' },
series: [{
type: 'bar',
data: mockData.regionSales,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
}
}]
};
barChart.setOption(barOption);
// 4. 实时销售监控
const realTimeChart = echarts.init(document.getElementById('realTimeChart'));
const realTimeOption = {
title: { text: '实时销售监控', left: 'center' },
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value', name: '订单数' },
series: [{
type: 'line',
data: [],
smooth: true,
areaStyle: { opacity: 0.2 },
itemStyle: { color: '#91cc75' }
}]
};
realTimeChart.setOption(realTimeOption);
// 模拟实时数据更新
let timeData = [];
let salesData = [];
let counter = 0;
setInterval(() => {
const now = new Date();
const timeStr = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
const sales = Math.floor(Math.random() * 50) + 10;
timeData.push(timeStr);
salesData.push(sales);
// 保持最近20个数据点
if (timeData.length > 20) {
timeData.shift();
salesData.shift();
}
realTimeChart.setOption({
xAxis: { data: timeData },
series: [{ data: salesData }]
});
counter++;
}, 2000);
// 更新当前时间
function updateTime() {
const now = new Date();
const timeStr = `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
document.getElementById('currentTime').textContent = timeStr;
}
setInterval(updateTime, 1000);
updateTime();
// 响应式处理
window.addEventListener('resize', () => {
trendChart.resize();
pieChart.resize();
barChart.resize();
realTimeChart.resize();
});
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initCharts);
第七部分:扩展与进阶
7.1 ECharts GL(3D图表)
ECharts GL是ECharts的WebGL扩展,支持3D图表、流场图等。
安装:
npm install echarts-gl --save
使用示例(3D柱状图):
import * as echarts from 'echarts';
import 'echarts-gl';
const chart = echarts.init(document.getElementById('main'));
const option = {
tooltip: {},
visualMap: {
max: 20,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
}
},
xAxis3D: {
type: 'category',
data: ['A', 'B', 'C', 'D', 'E']
},
yAxis3D: {
type: 'category',
data: ['X', 'Y', 'Z']
},
zAxis3D: {
type: 'value'
},
grid3D: {
viewControl: {
autoRotate: true
}
},
series: [{
type: 'bar3D',
data: [
[0, 0, 10], [0, 1, 15], [0, 2, 8],
[1, 0, 12], [1, 1, 18], [1, 2, 10],
[2, 0, 9], [2, 1, 14], [2, 2, 7],
[3, 0, 11], [3, 1, 16], [3, 2, 9],
[4, 0, 13], [4, 1, 20], [4, 2, 12]
],
shading: 'lambert',
label: {
show: false
}
}]
};
chart.setOption(option);
7.2 ECharts与D3.js结合
ECharts适合快速创建标准图表,D3.js适合高度自定义的可视化。两者可以结合使用。
思路:
- 使用D3.js处理复杂的数据转换和自定义绘制。
- 将处理后的数据传递给ECharts进行标准图表渲染。
- 或者使用D3.js绘制自定义图形,嵌入到ECharts的
custom系列中。
7.3 ECharts与大数据平台集成
ECharts可以与大数据平台(如Hadoop、Spark)结合,通过WebSocket或REST API获取实时数据流。
架构示例:
数据源 (Hadoop/Spark) → 数据处理 (Kafka/Flink) → 后端API (Node.js/Python) → 前端ECharts
WebSocket实时数据流示例:
// 前端WebSocket连接
const ws = new WebSocket('ws://your-server.com/data-stream');
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
// 更新ECharts图表
myChart.setOption({
series: [{
data: data.values
}]
});
};
第八部分:总结与资源推荐
8.1 本指南总结
本指南从ECharts的基础安装、核心概念讲起,详细介绍了多种图表类型的实战应用,涵盖了动态数据、交互事件、图表联动等高级功能,并提供了与Vue、React等前端框架的集成方案。最后通过一个完整的销售数据仪表盘项目,展示了ECharts在实际项目中的应用。此外,还介绍了性能优化技巧、常见问题解决方案以及ECharts GL等扩展内容。
8.2 学习资源推荐
- 官方文档:ECharts官方文档 - 最权威、最全面的学习资料。
- 示例中心:ECharts示例 - 包含大量可直接运行的示例代码。
- GitHub仓库:Apache ECharts GitHub - 获取最新代码和参与社区贡献。
- 在线编辑器:ECharts在线编辑器 - 实时编写和调试ECharts代码。
- 社区论坛:ECharts社区 - 提问和交流。
8.3 进一步学习路径
- 深入学习Option配置:掌握所有组件和系列的详细配置。
- 自定义系列开发:学习使用
custom系列进行高度自定义的绘制。 - 性能优化:针对大数据量、复杂交互场景进行优化。
- ECharts GL:探索3D图表和WebGL渲染。
- 与其他可视化库对比:了解D3.js、Highcharts、AntV等库的特点,选择最适合项目的工具。
通过本指南的学习和实践,你将能够熟练运用ECharts解决各种数据可视化需求,从简单的图表到复杂的数据仪表盘,都能游刃有余。祝你学习愉快,可视化之旅顺利!
