dataZoom 缩放
ECharts 数据区域缩放完全指南:滑块型与内置型详解
📖 概述
dataZoom 组件用于数据区域缩放,让用户能够聚焦数据的某一部分,是处理大规模时间序列数据的核心交互组件。
核心类型:
- 🔲 slider: 滑块型(显示缩略图)
- 🖱️ inside: 内置型(鼠标滚轮/触摸)
- 🎯 select: 选框型(框选缩放)
🔍 核心概念
1. 基础配置
javascript
option = {
dataZoom: [
{
type: 'slider', // 滑块型
start: 0, // 起始百分比(0-100)
end: 100, // 结束百分比
xAxisIndex: 0 // 控制的X轴索引
},
{
type: 'inside', // 内置型
start: 0,
end: 100
}
],
xAxis: { type: 'category', data: dates },
series: [{ type: 'line', data: values }]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2. Slider 型详解
javascript
dataZoom: [{
type: 'slider',
// 位置
left: '10%',
right: '10%',
bottom: 0,
height: 30,
// 范围
start: 0,
end: 50,
startValue: null, // 优先于start
endValue: null, // 优先于end
// 样式
handleSize: '100%',
handleStyle: {
color: '#5470c6',
borderColor: '#5470c6'
},
backgroundColor: '#f0f0f0',
fillerColor: 'rgba(84, 112, 198, 0.2)',
borderColor: '#ddd',
// 文本
textStyle: { color: '#999' },
// 是否显示细节
showDetail: true,
// 绑定轴
xAxisIndex: 0,
yAxisIndex: null
}]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
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
3. Inside 型详解
javascript
dataZoom: [{
type: 'inside',
// 范围
start: 0,
end: 100,
// 交互方式
zoomOnMouseWheel: true, // 滚轮缩放
moveOnMouseMove: true, // 拖拽平移
moveOnMouseWheel: false, // 滚轮平移
// 禁用
disabled: false,
// 绑定轴
xAxisIndex: 0
}]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
💡 使用场景
场景 1: 股票K线图缩放
javascript
const stockChart = {
title: { text: '股票K线图' },
tooltip: { trigger: 'axis' },
grid: { left: '3%', right: '3%', bottom: '15%' },
xAxis: {
type: 'category',
data: dates
},
yAxis: { scale: true },
dataZoom: [
{
type: 'slider',
top: '85%',
start: 50,
end: 100,
height: 40,
handleSize: '80%',
showDataShadow: true, // 显示数据阴影
filterMode: 'filter' // 过滤模式
},
{
type: 'inside',
start: 50,
end: 100,
zoomOnMouseWheel: true,
moveOnMouseMove: true
}
],
series: [{
type: 'candlestick',
data: ohlcData
}]
};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
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
场景 2: 实时数据流自动滚动
javascript
class RealtimeScrollChart {
constructor(dom, maxPoints = 100) {
this.chart = echarts.init(dom);
this.maxPoints = maxPoints;
this.data = [];
this.currentIndex = 0;
this.init();
}
init() {
this.chart.setOption({
title: { text: '实时数据监控' },
tooltip: { trigger: 'axis' },
grid: { left: '3%', right: '8%', bottom: '10%' },
xAxis: {
type: 'category',
data: []
},
yAxis: { type: 'value' },
dataZoom: [{
type: 'inside',
start: 0,
end: 100,
zoomLock: true // 锁定缩放,只允许平移
}],
series: [{
type: 'line',
data: [],
smooth: true
}]
});
// 模拟实时数据
setInterval(() => this.addData(), 1000);
}
addData() {
const now = new Date().toLocaleTimeString();
const value = Math.random() * 100;
this.data.push(value);
// 保持最大数据量
if (this.data.length > this.maxPoints) {
this.data.shift();
}
this.currentIndex++;
// 更新图表
this.chart.setOption({
xAxis: {
data: Array.from({ length: this.data.length }, (_, i) =>
`T-${this.data.length - i - 1}`
)
},
series: [{
data: [...this.data].reverse()
}]
});
// 自动滚动到最新数据
if (this.data.length >= this.maxPoints) {
const start = ((this.currentIndex - this.maxPoints) / this.currentIndex) * 100;
const end = 100;
this.chart.dispatchAction({
type: 'dataZoom',
start: start,
end: end
});
}
}
}
// 使用
new RealtimeScrollChart(document.getElementById('chart'), 50);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
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
场景 3: 多轴联动缩放
javascript
const multiAxisZoom = {
title: { text: '多指标对比' },
legend: { data: ['温度', '湿度'] },
grid: [
{ left: '3%', right: '4%', height: '40%', top: '10%' },
{ left: '3%', right: '4%', height: '40%', top: '55%' }
],
xAxis: [
{
type: 'category',
data: dates,
gridIndex: 0
},
{
type: 'category',
data: dates,
gridIndex: 1
}
],
yAxis: [
{ name: '温度(°C)', gridIndex: 0 },
{ name: '湿度(%)', gridIndex: 1 }
],
dataZoom: [
{
type: 'slider',
xAxisIndex: [0, 1], // 同时控制两个X轴
start: 0,
end: 50
},
{
type: 'inside',
xAxisIndex: [0, 1],
start: 0,
end: 50
}
],
series: [
{
name: '温度',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
data: tempData
},
{
name: '湿度',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
data: humidityData
}
]
};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
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
🔧 配置详解
完整配置项
javascript
dataZoom: [{
// 类型
type: 'slider', // 'slider' | 'inside' | 'select'
// 位置尺寸
left: '10%',
right: '10%',
top: 'auto',
bottom: 0,
width: 'auto',
height: 30,
// 范围控制
start: 0, // 起始百分比
end: 100, // 结束百分比
startValue: null, // 起始值(优先级高)
endValue: null, // 结束值(优先级高)
minSpan: 0, // 最小跨度
maxSpan: 100, // 最大跨度
minValueSpan: 0, // 最小值跨度
maxValueSpan: 0, // 最大值跨度
// 样式
backgroundColor: '#f0f0f0',
fillerColor: 'rgba(84, 112, 198, 0.2)',
borderColor: '#ddd',
handleSize: '100%',
handleIcon: 'path://...', // 自定义手柄图标
handleStyle: {
color: '#5470c6',
borderColor: '#5470c6'
},
// 文本
textStyle: {
color: '#999',
fontSize: 12
},
// 数据阴影
showDataShadow: true,
dataBackground: {
lineStyle: { color: '#aaa' },
areaStyle: { color: '#ccc' }
},
// 过滤器
filterMode: 'filter', // 'filter' | 'weakFilter' | 'empty' | 'none'
// 交互
zoomLock: false, // 锁定缩放
throttle: 100, // 节流(ms)
// 绑定
xAxisIndex: 0,
yAxisIndex: null,
// 其他
orient: 'horizontal', // 'horizontal' | 'vertical'
realtime: true, // 实时更新
brushSelect: true // 允许刷选
}]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
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
Filter Mode 详解
javascript
// 1. filter: 当前窗口外的数据不显示(推荐)
filterMode: 'filter'
// 2. weakFilter: 弱过滤,保留部分上下文
filterMode: 'weakFilter'
// 3. empty: 窗口外数据显示为空
filterMode: 'empty'
// 4. none: 不过滤,只改变坐标轴范围
filterMode: 'none'1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
📝 代码示例
示例: 完整的交互式缩放控制器
javascript
class ZoomController {
constructor(dom, data) {
this.chart = echarts.init(dom);
this.data = data;
this.currentStart = 0;
this.currentEnd = 100;
this.init();
}
init() {
this.render();
this.bindControls();
}
render() {
this.chart.setOption({
title: { text: '销售数据分析' },
tooltip: { trigger: 'axis' },
legend: { data: ['销售额'] },
grid: { left: '3%', right: '8%', bottom: '15%' },
xAxis: {
type: 'category',
data: this.data.map(d => d.date)
},
yAxis: { type: 'value' },
dataZoom: [
{
type: 'slider',
start: this.currentStart,
end: this.currentEnd,
bottom: 10,
height: 40,
showDataShadow: true,
realtime: true,
textStyle: { color: '#666' }
},
{
type: 'inside',
start: this.currentStart,
end: this.currentEnd
}
],
series: [{
name: '销售额',
type: 'line',
data: this.data.map(d => d.value),
smooth: true,
areaStyle: { opacity: 0.3 }
}]
});
// 监听缩放事件
this.chart.on('dataZoom', (params) => {
this.currentStart = params.start;
this.currentEnd = params.end;
console.log(`缩放范围: ${params.start.toFixed(1)}% - ${params.end.toFixed(1)}%`);
});
}
bindControls() {
// 重置按钮
document.getElementById('reset-zoom').addEventListener('click', () => {
this.resetZoom();
});
// 放大按钮
document.getElementById('zoom-in').addEventListener('click', () => {
this.zoomIn();
});
// 缩小按钮
document.getElementById('zoom-out').addEventListener('click', () => {
this.zoomOut();
});
}
resetZoom() {
this.currentStart = 0;
this.currentEnd = 100;
this.chart.dispatchAction({
type: 'dataZoom',
start: 0,
end: 100
});
}
zoomIn() {
const center = (this.currentStart + this.currentEnd) / 2;
const span = (this.currentEnd - this.currentStart) / 2;
this.currentStart = center - span / 2;
this.currentEnd = center + span / 2;
this.chart.dispatchAction({
type: 'dataZoom',
start: this.currentStart,
end: this.currentEnd
});
}
zoomOut() {
const center = (this.currentStart + this.currentEnd) / 2;
const span = (this.currentEnd - this.currentStart) * 2;
this.currentStart = Math.max(0, center - span / 2);
this.currentEnd = Math.min(100, center + span / 2);
this.chart.dispatchAction({
type: 'dataZoom',
start: this.currentStart,
end: this.currentEnd
});
}
// 编程式设置缩放范围
setZoomRange(start, end) {
this.currentStart = start;
this.currentEnd = end;
this.chart.dispatchAction({
type: 'dataZoom',
start,
end
});
}
}
// 使用
const controller = new ZoomController(
document.getElementById('chart'),
generateData(365)
);
function generateData(days) {
return Array.from({ length: days }, (_, i) => ({
date: `2024-${String(Math.floor(i / 30) + 1).padStart(2, '0')}-${String(i % 30 + 1).padStart(2, '0')}`,
value: Math.floor(Math.random() * 10000) + 5000
}));
}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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
⚠️ 常见问题
Q1: 缩放后数据不对?
javascript
// ✅ 使用 filterMode: 'filter'
dataZoom: [{
type: 'slider',
filterMode: 'filter' // 过滤窗口外数据
}]
// ❌ 避免使用 'none'
filterMode: 'none' // 可能导致数据显示错误1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Q2: 如何禁用缩放?
javascript
dataZoom: [{
type: 'inside',
disabled: true // 完全禁用
}]
// 或锁定缩放,只允许平移
dataZoom: [{
type: 'inside',
zoomLock: true
}]1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Q3: 如何监听缩放变化?
javascript
chart.on('dataZoom', (params) => {
console.log('起始:', params.start);
console.log('结束:', params.end);
console.log('起始值:', params.startValue);
console.log('结束值:', params.endValue);
});1
2
3
4
5
6
2
3
4
5
6
🎯 最佳实践
1. 性能优化
javascript
// 大数据时使用节流
dataZoom: [{
type: 'inside',
throttle: 100 // 100ms节流
}]1
2
3
4
5
2
3
4
5
2. 用户体验
javascript
// 显示数据阴影,帮助用户理解
dataZoom: [{
type: 'slider',
showDataShadow: true,
realtime: true // 实时更新
}]1
2
3
4
5
6
2
3
4
5
6
3. 移动端适配
javascript
// 移动端优化
if (isMobile) {
dataZoom: [{
type: 'inside',
zoomOnMouseWheel: false, // 禁用滚轮
moveOnMouseMove: true // 启用拖拽
}]
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
📊 性能指标
| 数据量 | 缩放响应时间 | 建议 |
|---|---|---|
| < 1K | < 10ms | 无限制 |
| 1K-10K | 10-50ms | 正常 |
| 10K-100K | 50-200ms | 开启throttle |
| > 100K | > 200ms | 使用filterMode |
🔗 相关链接
最后更新: 2026-04-23
难度等级: ⭐⭐⭐
预计阅读时间: 20 分钟
数据缩放组件
{
"title": {
"text": "大数据量展示",
"left": "center"
},
"tooltip": {
"trigger": "axis"
},
"grid": {
"bottom": 80
},
"xAxis": {
"type": "category",
"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天"
]
},
"yAxis": {
"type": "value"
},
"dataZoom": [
{
"type": "slider",
"start": 0,
"end": 30,
"bottom": 10
},
{
"type": "inside",
"start": 0,
"end": 30
}
],
"series": [
{
"type": "line",
"smooth": true,
"data": [
411,
162,
110,
263,
502,
127,
340,
172,
465,
386,
118,
192,
527,
188,
189,
139,
402,
338,
156,
360,
263,
107,
135,
181,
258,
391,
374,
399,
155,
211,
578,
535,
101,
132,
157,
395,
277,
460,
391,
388,
332,
143,
487,
572,
273,
132,
230,
191,
474,
409
],
"itemStyle": {
"color": "#5470c6"
}
}
]
}最后更新: 2026-04-23
难度等级: ⭐⭐⭐
预计阅读时间: 20 分钟
