ECharts 高级功能 #
本章将介绍 ECharts 的高级功能,帮助你实现更复杂的数据可视化需求。
地图可视化 #
地图基础 #
javascript
// 引入中国地图数据
import 'echarts/map/js/china.js';
const option = {
title: {
text: '中国地图',
left: 'center'
},
tooltip: {
trigger: 'item'
},
visualMap: {
min: 0,
max: 100,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true
},
series: [{
name: '数据',
type: 'map',
map: 'china',
roam: true,
label: {
show: true
},
data: [
{ name: '北京', value: 80 },
{ name: '上海', value: 90 },
{ name: '广东', value: 70 }
]
}]
};
地图样式 #
javascript
series: [{
type: 'map',
map: 'china',
// 地图区域样式
itemStyle: {
areaColor: '#f3f3f3',
borderColor: '#999',
borderWidth: 0.5
},
// 高亮样式
emphasis: {
itemStyle: {
areaColor: '#e0e0e0',
borderColor: '#666',
borderWidth: 1
},
label: {
show: true,
color: '#333'
}
},
// 选中样式
select: {
itemStyle: {
areaColor: '#ccc'
}
},
// 标签
label: {
show: false,
color: '#333',
fontSize: 10
}
}]
散点地图 #
javascript
const option = {
geo: {
map: 'china',
roam: true,
label: { show: false },
itemStyle: {
areaColor: '#f3f3f3',
borderColor: '#999'
}
},
series: [{
name: '城市',
type: 'scatter',
coordinateSystem: 'geo',
data: [
{ name: '北京', value: [116.46, 39.92, 100] },
{ name: '上海', value: [121.48, 31.22, 200] },
{ name: '广州', value: [113.23, 23.16, 150] }
],
symbolSize: function(val) {
return val[2] / 10;
},
itemStyle: {
color: '#5470c6'
}
}]
};
热力地图 #
javascript
const option = {
geo: {
map: 'china',
roam: true
},
visualMap: {
min: 0,
max: 100,
calculable: true,
inRange: {
color: ['#50a3ba', '#eac736', '#d94e5d']
}
},
series: [{
name: '热力',
type: 'heatmap',
coordinateSystem: 'geo',
data: [
[116.46, 39.92, 80],
[121.48, 31.22, 90],
[113.23, 23.16, 70]
]
}]
};
迁徙图 #
javascript
const option = {
geo: {
map: 'china',
roam: true
},
series: [{
name: '迁徙',
type: 'lines',
coordinateSystem: 'geo',
zlevel: 2,
effect: {
show: true,
period: 6,
trailLength: 0.7,
color: '#fff',
symbolSize: 3
},
lineStyle: {
color: '#a6c84c',
width: 1,
curveness: 0.2
},
data: [
{
fromName: '北京',
toName: '上海',
coords: [[116.46, 39.92], [121.48, 31.22]]
},
{
fromName: '北京',
toName: '广州',
coords: [[116.46, 39.92], [113.23, 23.16]]
}
]
}]
};
3D 图表 #
3D 柱状图 #
javascript
// 需要引入 echarts-gl
import 'echarts-gl';
const option = {
title: {
text: '3D 柱状图'
},
xAxis3D: {
type: 'category',
data: ['A', 'B', 'C', 'D']
},
yAxis3D: {
type: 'category',
data: ['X', 'Y', 'Z']
},
zAxis3D: {
type: 'value'
},
grid3D: {
boxWidth: 100,
boxHeight: 50,
boxDepth: 80,
viewControl: {
autoRotate: true
}
},
series: [{
type: 'bar3D',
data: [
['A', 'X', 10],
['A', 'Y', 20],
['A', 'Z', 30],
['B', 'X', 15],
['B', 'Y', 25],
['B', 'Z', 35]
],
shading: 'lambert',
label: {
show: true
},
itemStyle: {
opacity: 0.8
}
}]
};
3D 散点图 #
javascript
const option = {
xAxis3D: { type: 'value' },
yAxis3D: { type: 'value' },
zAxis3D: { type: 'value' },
grid3D: {
viewControl: {
autoRotate: true
}
},
series: [{
type: 'scatter3D',
data: [
[10, 20, 30],
[15, 25, 35],
[20, 30, 40]
],
symbolSize: 12,
itemStyle: {
color: '#5470c6',
opacity: 0.8
}
}]
};
3D 曲面图 #
javascript
const option = {
visualMap: {
show: false,
dimension: 2,
min: -1,
max: 1,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8']
}
},
xAxis3D: { type: 'value' },
yAxis3D: { type: 'value' },
zAxis3D: { type: 'value' },
grid3D: {
viewControl: {
autoRotate: true
}
},
series: [{
type: 'surface',
wireframe: {
show: false
},
shading: 'color',
equation: {
x: { step: 0.05 },
y: { step: 0.05 },
z: function(x, y) {
return Math.sin(x) * Math.cos(y);
}
}
}]
};
3D 地图 #
javascript
const option = {
geo3D: {
map: 'china',
roam: true,
itemStyle: {
areaColor: '#5470c6',
opacity: 0.8
},
emphasis: {
itemStyle: {
color: '#91cc75'
}
},
light: {
main: {
intensity: 1.2,
shadow: true
},
ambient: {
intensity: 0.3
}
},
viewControl: {
autoRotate: true,
distance: 100
}
}
};
大数据优化 #
增量渲染 #
javascript
// 分批添加数据
function appendDataInBatches(chart, data, batchSize = 1000) {
let index = 0;
function appendNextBatch() {
const batch = data.slice(index, index + batchSize);
chart.appendData({
seriesIndex: 0,
data: batch
});
index += batchSize;
if (index < data.length) {
requestAnimationFrame(appendNextBatch);
}
}
appendNextBatch();
}
大数据模式 #
javascript
option = {
series: [{
type: 'line',
data: largeData,
// 开启大数据优化
large: true,
largeThreshold: 2000,
// 简化样式
symbol: 'none',
sampling: 'lttb', // 'lttb', 'average', 'max', 'min', 'sum'
// 简化动画
animation: false
}]
};
数据采样 #
javascript
// LTTB 采样算法
option = {
series: [{
type: 'line',
data: largeData,
sampling: 'lttb'
}]
};
// 自定义采样
function sampleData(data, maxPoints) {
if (data.length <= maxPoints) return data;
const step = Math.ceil(data.length / maxPoints);
const sampled = [];
for (let i = 0; i < data.length; i += step) {
sampled.push(data[i]);
}
return sampled;
}
性能优化配置 #
javascript
option = {
// 关闭动画
animation: false,
animationThreshold: 2000,
// 关闭渐进渲染
progressive: 0,
progressiveThreshold: 3000,
series: [{
type: 'scatter',
data: largeData,
// 大数据模式
large: true,
largeThreshold: 2000,
// 简化样式
symbol: 'circle',
symbolSize: 3,
// 简化渲染
itemStyle: {
opacity: 0.6
}
}]
};
自定义系列 #
基础自定义系列 #
javascript
option = {
series: [{
type: 'custom',
renderItem: function(params, api) {
// 获取数据
const value = api.value(0);
const coord = api.coord([value, 0]);
// 返回图形元素
return {
type: 'circle',
shape: {
cx: coord[0],
cy: coord[1],
r: 10
},
style: {
fill: '#5470c6'
}
};
},
data: [10, 20, 30, 40, 50]
}]
};
自定义柱状图 #
javascript
option = {
xAxis: {
type: 'category',
data: ['A', 'B', 'C', 'D']
},
yAxis: { type: 'value' },
series: [{
type: 'custom',
renderItem: function(params, api) {
const categoryIndex = api.value(0);
const value = api.value(1);
const start = api.coord([categoryIndex, 0]);
const end = api.coord([categoryIndex, value]);
const width = api.size([1, 0])[0] * 0.6;
return {
type: 'rect',
shape: {
x: end[0] - width / 2,
y: end[1],
width: width,
height: start[1] - end[1]
},
style: {
fill: api.visual('color')
}
};
},
encode: {
x: 0,
y: 1
},
data: [
['A', 10],
['B', 20],
['C', 30],
['D', 40]
]
}]
};
自定义动画 #
javascript
option = {
series: [{
type: 'custom',
renderItem: function(params, api) {
const point = api.coord([api.value(0), api.value(1)]);
return {
type: 'circle',
shape: {
cx: point[0],
cy: point[1],
r: 0
},
style: {
fill: '#5470c6'
},
// 入场动画
during: function(apiDuring) {
apiDuring.setStyle('r', apiDuring.r * 10);
},
// 更新动画
transition: ['shape'],
enterFrom: { style: { opacity: 0 } }
};
},
data: [[0, 10], [1, 20], [2, 30]]
}]
};
多图表联动 #
connect 方法 #
javascript
// 创建多个图表
const chart1 = echarts.init(document.getElementById('chart1'));
const chart2 = echarts.init(document.getElementById('chart2'));
// 设置配置
chart1.setOption(option1);
chart2.setOption(option2);
// 联动
echarts.connect([chart1, chart2]);
group 联动 #
javascript
// 设置分组
const chart1 = echarts.init(document.getElementById('chart1'));
const chart2 = echarts.init(document.getElementById('chart2'));
chart1.group = 'group1';
chart2.group = 'group1';
echarts.connect('group1');
事件联动 #
javascript
// 通过事件实现联动
chart1.on('datazoom', function(params) {
chart2.dispatchAction({
type: 'dataZoom',
start: params.start,
end: params.end
});
});
chart1.on('highlight', function(params) {
chart2.dispatchAction({
type: 'highlight',
seriesIndex: params.seriesIndex,
dataIndex: params.dataIndex
});
});
动态数据更新 #
实时数据 #
javascript
// WebSocket 实时数据
const ws = new WebSocket('ws://example.com/data');
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
chart.setOption({
series: [{
data: data
}]
});
};
// 轮询更新
setInterval(function() {
fetch('/api/data')
.then(response => response.json())
.then(data => {
chart.setOption({
series: [{ data: data }]
});
});
}, 3000);
数据滚动 #
javascript
const data = [];
const maxPoints = 100;
setInterval(function() {
// 添加新数据
data.push(Math.random() * 100);
// 保持最大数量
if (data.length > maxPoints) {
data.shift();
}
chart.setOption({
series: [{
data: data
}]
});
}, 1000);
动态添加系列 #
javascript
function addSeries(chart, name, data) {
const option = chart.getOption();
option.series.push({
name: name,
type: 'line',
data: data
});
option.legend[0].data.push(name);
chart.setOption(option);
}
导出功能 #
导出图片 #
javascript
// 获取图片数据 URL
const imageDataURL = chart.getDataURL({
type: 'png', // 'png', 'jpeg', 'svg'
pixelRatio: 2,
backgroundColor: '#fff'
});
// 下载图片
const link = document.createElement('a');
link.download = 'chart.png';
link.href = imageDataURL;
link.click();
导出 SVG #
javascript
// 需要使用 SVG 渲染器
const chart = echarts.init(dom, null, {
renderer: 'svg'
});
// 获取 SVG
const svgData = chart.getDataURL({
type: 'svg'
});
导出数据 #
javascript
// 获取图表数据
const option = chart.getOption();
const data = option.series[0].data;
// 导出为 JSON
const jsonData = JSON.stringify(data, null, 2);
const blob = new Blob([jsonData], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = 'data.json';
link.href = url;
link.click();
最佳实践 #
1. 性能优化清单 #
text
□ 关闭不必要的动画
□ 使用大数据模式
□ 合理设置采样
□ 分批加载数据
□ 使用增量渲染
□ 优化数据结构
□ 减少重绘次数
2. 内存管理 #
javascript
// 及时销毁不需要的图表
function destroyChart(chart) {
if (chart) {
chart.clear();
chart.dispose();
}
}
// 页面卸载时清理
window.addEventListener('beforeunload', function() {
destroyChart(chart);
});
3. 错误处理 #
javascript
try {
chart.setOption(option);
} catch (error) {
console.error('ECharts 配置错误:', error);
// 显示错误提示
chart.showLoading({
text: '图表加载失败',
color: '#ee6666'
});
}
总结 #
恭喜你完成了 ECharts 完全指南的学习!现在你已经掌握了:
- ECharts 的基础概念和安装配置
- 各种常见图表的实现方法
- 丰富的交互功能
- 主题和样式定制
- 地图可视化和 3D 图表
- 大数据优化和性能调优
- 自定义系列和高级功能
继续实践和探索,你将成为数据可视化专家!
资源推荐 #
最后更新:2026-03-28