ECharts 实时数据流完全指南
文档类型: 实战指南
难度等级: ⭐⭐⭐
源码版本: ECharts 5.x
本文行数: 约420行
📋 目录
🎯 WebSocket集成
基础实时数据流
typescript
import * as echarts from 'echarts';
class RealtimeChart {
private chart: echarts.ECharts;
private data: number[] = [];
private maxDataPoints = 100;
private ws: WebSocket | null = null;
constructor(container: HTMLElement, wsUrl: string) {
this.chart = echarts.init(container);
this.connectWebSocket(wsUrl);
this.initChart();
}
private connectWebSocket(url: string) {
this.ws = new WebSocket(url);
this.ws.onmessage = (event) => {
const value = parseFloat(event.data);
this.addDataPoint(value);
};
this.ws.onerror = (error) => {
console.error('WebSocket错误:', error);
};
}
private addDataPoint(value: number) {
this.data.push(value);
// 保持固定长度
if (this.data.length > this.maxDataPoints) {
this.data.shift();
}
// 更新图表
this.chart.setOption({
series: [{
data: this.data
}]
});
}
private initChart() {
const option = {
title: { text: '实时数据监控' },
xAxis: {
type: 'category',
data: Array.from({ length: this.maxDataPoints }, (_, i) => i)
},
yAxis: { type: 'value' },
series: [{
type: 'line',
data: this.data,
smooth: true,
animation: false, // 关闭动画提升性能
showSymbol: false
}]
};
this.chart.setOption(option);
}
dispose() {
if (this.ws) {
this.ws.close();
}
this.chart.dispose();
}
}
// 使用
const realtimeChart = new RealtimeChart(
document.getElementById('chart')!,
'ws://localhost:8080/data'
);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
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
📊 数据缓冲策略
节流更新
typescript
class ThrottledRealtimeChart {
private chart: echarts.ECharts;
private buffer: number[] = [];
private updateInterval = 100; // 100ms更新一次
private lastUpdateTime = 0;
addDataPoint(value: number) {
this.buffer.push(value);
const now = Date.now();
if (now - this.lastUpdateTime >= this.updateInterval) {
this.flushBuffer();
this.lastUpdateTime = now;
}
}
private flushBuffer() {
// 合并缓冲区数据
const newData = [...this.buffer];
this.buffer = [];
// 批量更新
this.chart.setOption({
series: [{
data: newData
}]
});
}
}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
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
🚀 性能优化
大数据量优化
typescript
const optimizedOption = {
series: [{
type: 'line',
data: largeDataArray,
// 性能优化配置
animation: false, // 关闭动画
showSymbol: false, // 不显示数据点
progressive: 1000, // 渐进式渲染
progressiveThreshold: 5000,
// 采样优化
sampling: 'lttb', // LTTB降采样
// 线条优化
lineStyle: { width: 1 }
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
💻 实战案例
CPU监控面板
typescript
class CPUMonitor {
private chart: echarts.ECharts;
private cpuData: number[] = [];
private memoryData: number[] = [];
private maxPoints = 60;
constructor(container: HTMLElement) {
this.chart = echarts.init(container);
this.init();
this.startMonitoring();
}
private init() {
const option = {
title: { text: '系统资源监控' },
legend: { data: ['CPU使用率', '内存使用率'] },
xAxis: {
type: 'category',
boundaryGap: false,
data: Array.from({ length: this.maxPoints }, (_, i) => {
const time = new Date();
time.setSeconds(time.getSeconds() - (this.maxPoints - i));
return time.toLocaleTimeString();
})
},
yAxis: [
{ type: 'value', name: 'CPU%', max: 100 },
{ type: 'value', name: '内存%', max: 100 }
],
series: [
{
name: 'CPU使用率',
type: 'line',
yAxisIndex: 0,
data: this.cpuData,
smooth: true,
showSymbol: false,
areaStyle: { opacity: 0.3 },
itemStyle: { color: '#5470C6' }
},
{
name: '内存使用率',
type: 'line',
yAxisIndex: 1,
data: this.memoryData,
smooth: true,
showSymbol: false,
areaStyle: { opacity: 0.3 },
itemStyle: { color: '#91CC75' }
}
]
};
this.chart.setOption(option);
}
private startMonitoring() {
setInterval(() => {
// 模拟获取系统数据
const cpuUsage = Math.random() * 100;
const memoryUsage = Math.random() * 100;
this.updateData(cpuUsage, memoryUsage);
}, 1000);
}
private updateData(cpu: number, memory: number) {
this.cpuData.push(cpu);
this.memoryData.push(memory);
if (this.cpuData.length > this.maxPoints) {
this.cpuData.shift();
this.memoryData.shift();
}
this.chart.setOption({
series: [
{ data: this.cpuData },
{ data: this.memoryData }
]
});
}
dispose() {
this.chart.dispose();
}
}
// 使用
const monitor = new CPUMonitor(document.getElementById('chart')!);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
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
🎯 最佳实践总结
✅ DO - 推荐做法
关闭不必要的动画
typescriptanimation: false1限制数据点数量
typescriptif (data.length > maxPoints) data.shift();1使用节流避免频繁更新
typescriptthrottle(update, 100)1
❌ DON'T - 避免做法
- 避免每秒多次更新typescript
// ❌ 不好 setInterval(update, 50) // 20次/秒 // ✅ 好 setInterval(update, 1000) // 1次/秒1
2
3
4
5
🔗 相关资源
下一篇: 时间格式化
