ECharts 移动端优化完全指南
文档类型: 实战指南
难度等级: ⭐⭐⭐
源码版本: ECharts 5.x
本文行数: 约400行
📋 目录
🎯 性能优化
减少数据量
typescript
const mobileOption = {
series: [{
type: 'line',
data: sampledData, // 抽样后的数据
// 关闭动画
animation: false,
// 简化图形
showSymbol: false,
symbolSize: 4,
// 线条优化
lineStyle: { width: 1.5 }
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
启用大数据模式
typescript
const option = {
series: [{
type: 'scatter',
data: largeData,
// 大数据优化
large: true,
largeThreshold: 2000,
progressive: 1000,
progressiveThreshold: 5000
}]
};1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
👆 交互优化
触摸友好的配置
typescript
const touchFriendlyOption = {
tooltip: {
trigger: 'axis',
// 移动端优化
confine: true, // 限制在容器内
extraCssText: 'max-width: 200px;',
textStyle: {
fontSize: 12
}
},
legend: {
type: 'scroll', // 可滚动图例
pageButtonItemGap: 5,
pageButtonPosition: 'end'
},
grid: {
containLabel: true // 包含标签
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
手势支持
typescript
// 双指缩放
chart.on('mousewheel', (params: any) => {
if (params.event.ctrlKey || params.event.metaKey) {
// Ctrl + 滚轮 = 缩放
const zoomFactor = params.event.deltaY > 0 ? 0.9 : 1.1;
chart.dispatchAction({
type: 'dataZoom',
start: chart.getOption().dataZoom[0].start * zoomFactor,
end: chart.getOption().dataZoom[0].end * zoomFactor
});
}
});1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
📱 触摸事件
自定义触摸行为
typescript
class TouchOptimizer {
private chart: echarts.ECharts;
private touchStartX: number = 0;
private touchStartY: number = 0;
constructor(container: HTMLElement, option: any) {
this.chart = echarts.init(container);
this.chart.setOption(option);
this.setupTouchEvents(container);
}
private setupTouchEvents(container: HTMLElement) {
container.addEventListener('touchstart', (e: TouchEvent) => {
if (e.touches.length === 1) {
this.touchStartX = e.touches[0].clientX;
this.touchStartY = e.touches[0].clientY;
}
});
container.addEventListener('touchmove', (e: TouchEvent) => {
if (e.touches.length === 1) {
const deltaX = e.touches[0].clientX - this.touchStartX;
const deltaY = e.touches[0].clientY - this.touchStartY;
// 水平滑动 = 平移图表
if (Math.abs(deltaX) > Math.abs(deltaY)) {
e.preventDefault();
this.panChart(deltaX);
}
}
});
}
private panChart(deltaX: number) {
const option = this.chart.getOption();
const currentStart = option.dataZoom?.[0]?.start || 0;
const currentEnd = option.dataZoom?.[0]?.end || 100;
const range = currentEnd - currentStart;
const shift = (deltaX / window.innerWidth) * range;
let newStart = currentStart - shift;
let newEnd = currentEnd - shift;
// 限制范围
if (newStart < 0) {
newStart = 0;
newEnd = range;
}
if (newEnd > 100) {
newEnd = 100;
newStart = 100 - range;
}
this.chart.dispatchAction({
type: 'dataZoom',
start: newStart,
end: newEnd
});
}
dispose() {
this.chart.dispose();
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
💻 实战案例
案例1: 移动端Dashboard
typescript
class MobileDashboard {
private chart: echarts.ECharts;
constructor(container: HTMLElement) {
this.chart = echarts.init(container);
this.render();
}
private render() {
const isMobile = window.innerWidth < 768;
const option = {
title: {
text: '销售数据',
textStyle: {
fontSize: isMobile ? 14 : 18
}
},
tooltip: {
trigger: 'axis',
confine: true,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
textStyle: {
color: '#fff',
fontSize: 12
}
},
legend: {
data: ['销售额', '利润'],
bottom: 0,
textStyle: {
fontSize: isMobile ? 10 : 12
}
},
grid: {
left: isMobile ? '15%' : '10%',
right: isMobile ? '5%' : '10%',
top: '15%',
bottom: isMobile ? '20%' : '10%'
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五'],
axisLabel: {
fontSize: isMobile ? 10 : 12,
rotate: isMobile ? 45 : 0
}
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: isMobile ? 10 : 12
}
},
series: [
{
name: '销售额',
type: 'bar',
data: [120, 200, 150, 80, 70],
barWidth: isMobile ? '40%' : '50%'
},
{
name: '利润',
type: 'line',
data: [30, 50, 40, 20, 15],
smooth: true,
symbolSize: isMobile ? 4 : 8
}
]
};
this.chart.setOption(option);
}
resize() {
this.chart.resize();
this.render(); // 重新渲染以应用新配置
}
dispose() {
this.chart.dispose();
}
}
// 使用
const dashboard = new MobileDashboard(document.getElementById('chart')!);
window.addEventListener('resize', debounce(() => dashboard.resize(), 300));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
🎯 最佳实践总结
✅ DO - 推荐做法
减少数据点数量
typescript// 抽样到100个点以内 data: sample(rawData, 100)1
2关闭不必要的特效
typescriptanimation: false showSymbol: false1
2使用confine限制tooltip
typescripttooltip: { confine: true }1
❌ DON'T - 避免做法
- 避免过多交互typescript
// ❌ 不好 - 移动端复杂交互 emphasis: { scale: true, focus: 'series' } // ✅ 好 - 简化 emphasis: { disabled: true }1
2
3
4
5
🔗 相关资源
✅ 部署导出模块完成!
