内置主题完全指南 - dark与vintage
📋 概述
ECharts提供了多个精心设计的内置主题,可以直接应用到图表中。其中**dark(暗色主题)和vintage(复古主题)**是最常用的两个主题。合理使用主题可以大幅提升数据可视化的美观度和可读性。
核心价值
- 快速美化:一行代码应用专业配色方案
- 场景适配:不同主题适应不同展示场景
- 品牌一致:保持整个应用的视觉统一性
- 用户友好:考虑色盲、暗光环境等可访问性
🎯 内置主题列表
1. 默认主题(无名称)
javascript
// 不指定主题即使用默认主题
const chart = echarts.init(dom);1
2
2
特点:
- 明亮的浅色背景
- 鲜艳的彩色配色
- 适合大多数场景
- 打印友好
典型用途:
- 数据报告
- 商业演示
- 网页展示
2. dark(暗色主题)
javascript
const chart = echarts.init(dom, 'dark');1
特点:
- 深色背景(#333)
- 高对比度配色
- 霓虹色调
- 科技感强
典型用途:
- 数据大屏
- 监控面板
- 夜间模式
- 科技产品展示
3. vintage(复古主题)
javascript
const chart = echarts.init(dom, 'vintage');1
特点:
- 米黄色背景(#fef8ef)
- 暖色调配色
- 怀旧风格
- 优雅柔和
典型用途:
- 历史数据展示
- 文化艺术类应用
- 纸质报告风格
- 教育场景
4. 其他内置主题
| 主题名 | 背景色 | 风格 | 适用场景 |
|---|---|---|---|
light | #fff | 明亮简洁 | 通用 |
default | #fff | 标准配色 | 通用 |
dark | #333 | 暗色科技 | 大屏、监控 |
vintage | #fef8ef | 复古优雅 | 文化、教育 |
🔧 使用方式
基础用法
javascript
// 方式1:初始化时指定主题
const chart = echarts.init(dom, 'dark');
// 方式2:动态切换主题
chart.dispose(); // 销毁旧实例
chart = echarts.init(dom, 'vintage'); // 重新初始化
chart.setOption(option); // 重新设置配置
// 方式3:根据系统主题自动切换
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = isDarkMode ? 'dark' : 'default';
const chart = echarts.init(dom, theme);1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
完整示例
javascript
// HTML
<div id="main" style="width: 800px; height: 600px;"></div>
// JavaScript
const dom = document.getElementById('main');
// 暗色主题
const chart = echarts.init(dom, 'dark');
const option = {
title: {
text: '销售数据分析',
left: 'center',
textStyle: {
color: '#fff' // 暗色主题下文字颜色
}
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(50,50,50,0.7)', // 提示框背景
borderColor: '#777',
textStyle: {
color: '#fff'
}
},
legend: {
data: ['销售额', '利润'],
textStyle: {
color: '#ccc'
},
top: 30
},
xAxis: {
type: 'category',
data: ['一月', '二月', '三月', '四月', '五月'],
axisLine: {
lineStyle: {
color: '#999' // 轴线颜色
}
},
axisLabel: {
color: '#ccc' // 刻度标签颜色
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#999'
}
},
axisLabel: {
color: '#ccc'
},
splitLine: {
lineStyle: {
color: '#444' // 分割线颜色
}
}
},
series: [
{
name: '销售额',
type: 'bar',
data: [120, 200, 150, 80, 70],
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
}
},
{
name: '利润',
type: 'line',
data: [20, 50, 30, 20, 15],
itemStyle: {
color: '#ffc107'
}
}
]
};
chart.setOption(option);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
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
💡 实战案例
案例1:暗色主题数据大屏
javascript
class DarkDashboard {
constructor(container) {
this.chart = echarts.init(container, 'dark');
this.init();
}
init() {
const option = {
backgroundColor: '#1a1a2e', // 深蓝紫色背景
title: {
text: '实时监控中心',
left: 'center',
textStyle: {
color: '#00ffcc',
fontSize: 24,
fontWeight: 'bold'
},
subtext: '数据更新时间:' + new Date().toLocaleTimeString(),
subtextStyle: {
color: '#888'
}
},
// 网格布局
grid: [
{ left: '5%', top: '15%', width: '45%', height: '35%' },
{ right: '5%', top: '15%', width: '45%', height: '35%' },
{ left: '5%', bottom: '5%', width: '45%', height: '35%' },
{ right: '5%', bottom: '5%', width: '45%', height: '35%' }
],
// 第一个图表:流量趋势
xAxis: [{
type: 'category',
gridIndex: 0,
data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
axisLine: { lineStyle: { color: '#444' } },
axisLabel: { color: '#888' }
}],
yAxis: [{
gridIndex: 0,
type: 'value',
splitLine: { lineStyle: { color: '#333' } },
axisLabel: { color: '#888' }
}],
series: [{
name: '访问量',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
smooth: true,
data: [820, 932, 901, 934, 1290, 1330],
lineStyle: {
color: '#00ffcc',
width: 3
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(0, 255, 204, 0.3)' },
{ offset: 1, color: 'rgba(0, 255, 204, 0.05)' }
])
}
}],
// 第二个图表:饼图
series: [{
name: '设备分布',
type: 'pie',
center: ['75%', '32.5%'],
radius: ['30%', '50%'],
data: [
{ value: 335, name: 'PC端' },
{ value: 310, name: '移动端' },
{ value: 234, name: '平板' }
],
label: {
color: '#ccc'
},
emphasis: {
itemStyle: {
shadowBlur: 20,
shadowColor: 'rgba(0, 255, 204, 0.5)'
}
}
}],
// 第三个图表:柱状图
xAxis: [{
gridIndex: 2,
type: 'category',
data: ['服务器A', '服务器B', '服务器C', '服务器D'],
axisLine: { lineStyle: { color: '#444' } },
axisLabel: { color: '#888' }
}],
yAxis: [{
gridIndex: 2,
type: 'value',
splitLine: { lineStyle: { color: '#333' } },
axisLabel: { color: '#888' }
}],
series: [{
name: 'CPU使用率',
type: 'bar',
xAxisIndex: 2,
yAxisIndex: 2,
data: [65, 78, 45, 92],
itemStyle: {
color: function(params) {
const colors = ['#ff6b6b', '#feca57', '#48dbfb', '#ff9ff3'];
return colors[params.dataIndex];
}
}
}],
// 第四个图表:雷达图
series: [{
name: '性能指标',
type: 'radar',
center: ['75%', '82.5%'],
radius: '40%',
indicator: [
{ name: '响应时间', max: 100 },
{ name: '吞吐量', max: 100 },
{ name: '可用性', max: 100 },
{ name: '错误率', max: 100 },
{ name: '满意度', max: 100 }
],
data: [{
value: [85, 90, 95, 88, 92],
name: '当前状态'
}],
lineStyle: {
color: '#00ffcc'
},
areaStyle: {
color: 'rgba(0, 255, 204, 0.3)'
}
}]
};
this.chart.setOption(option);
}
// 更新数据
updateData(newData) {
this.chart.setOption({
series: newData
});
}
// 销毁
dispose() {
this.chart.dispose();
}
}
// 使用
const dashboard = new DarkDashboard(document.getElementById('dashboard'));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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
案例2:复古主题财务报表
javascript
const chart = echarts.init(document.getElementById('report'), 'vintage');
const option = {
backgroundColor: '#fef8ef', // 米黄色背景
title: {
text: '2023年度财务报告',
left: 'center',
textStyle: {
color: '#8b4513', // 棕色文字
fontSize: 28,
fontFamily: 'Georgia, serif',
fontWeight: 'bold'
},
subtext: '数据来源:财务系统',
subtextStyle: {
color: '#a0522d'
}
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(254, 248, 239, 0.9)',
borderColor: '#d2b48c',
borderWidth: 1,
textStyle: {
color: '#5c4033'
}
},
legend: {
data: ['收入', '支出', '利润'],
top: 40,
textStyle: {
color: '#8b4513',
fontSize: 14
}
},
xAxis: {
type: 'category',
data: ['Q1', 'Q2', 'Q3', 'Q4'],
axisLine: {
lineStyle: {
color: '#d2b48c' // 棕褐色轴线
}
},
axisLabel: {
color: '#8b4513',
fontSize: 14,
fontFamily: 'Georgia, serif'
}
},
yAxis: {
type: 'value',
name: '金额(万元)',
nameTextStyle: {
color: '#8b4513',
fontSize: 14
},
axisLine: {
lineStyle: {
color: '#d2b48c'
}
},
axisLabel: {
color: '#8b4513',
formatter: '¥{value}'
},
splitLine: {
lineStyle: {
color: '#deb887',
type: 'dashed' // 虚线分割线
}
}
},
series: [
{
name: '收入',
type: 'bar',
barWidth: '25%',
data: [1200, 1500, 1800, 2100],
itemStyle: {
color: '#cd853f', // 秘鲁棕
borderRadius: [4, 4, 0, 0]
},
label: {
show: true,
position: 'top',
color: '#8b4513',
formatter: '¥{c}'
}
},
{
name: '支出',
type: 'bar',
barWidth: '25%',
data: [800, 950, 1100, 1300],
itemStyle: {
color: '#a0522d', // 赭石色
borderRadius: [4, 4, 0, 0]
},
label: {
show: true,
position: 'top',
color: '#8b4513',
formatter: '¥{c}'
}
},
{
name: '利润',
type: 'line',
smooth: true,
data: [400, 550, 700, 800],
lineStyle: {
color: '#556b2f', // 深橄榄绿
width: 3
},
itemStyle: {
color: '#6b8e23'
},
symbol: 'circle',
symbolSize: 8,
label: {
show: true,
position: 'top',
color: '#556b2f',
formatter: '¥{c}',
fontWeight: 'bold'
}
}
]
};
chart.setOption(option);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
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
案例3:主题切换功能
javascript
class ThemeSwitcher {
constructor(dom, option) {
this.dom = dom;
this.option = option;
this.currentTheme = 'default';
this.chart = null;
this.init();
this.bindEvents();
}
init() {
this.chart = echarts.init(this.dom, this.currentTheme);
this.chart.setOption(this.option);
}
bindEvents() {
// 主题切换按钮
document.getElementById('switch-theme').addEventListener('click', () => {
this.toggleTheme();
});
// 监听系统主题变化
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
this.setTheme(e.matches ? 'dark' : 'default');
});
}
toggleTheme() {
const themes = ['default', 'dark', 'vintage'];
const currentIndex = themes.indexOf(this.currentTheme);
const nextIndex = (currentIndex + 1) % themes.length;
this.setTheme(themes[nextIndex]);
}
setTheme(themeName) {
// 销毁旧图表
if (this.chart) {
this.chart.dispose();
}
// 创建新图表
this.currentTheme = themeName;
this.chart = echarts.init(this.dom, themeName);
this.chart.setOption(this.option);
// 更新UI
this.updateUI(themeName);
// 保存偏好
localStorage.setItem('echarts-theme', themeName);
}
updateUI(themeName) {
const labels = {
'default': '默认主题',
'dark': '暗色主题',
'vintage': '复古主题'
};
document.getElementById('current-theme').textContent = labels[themeName];
// 根据主题调整页面背景
const body = document.body;
if (themeName === 'dark') {
body.style.backgroundColor = '#333';
body.style.color = '#fff';
} else if (themeName === 'vintage') {
body.style.backgroundColor = '#fef8ef';
body.style.color = '#5c4033';
} else {
body.style.backgroundColor = '#fff';
body.style.color = '#333';
}
}
// 恢复用户偏好
restorePreference() {
const saved = localStorage.getItem('echarts-theme');
if (saved) {
this.setTheme(saved);
} else {
// 检测系统主题
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
this.setTheme(isDark ? 'dark' : 'default');
}
}
// 销毁
dispose() {
if (this.chart) {
this.chart.dispose();
}
}
}
// 使用
const themeSwitcher = new ThemeSwitcher(
document.getElementById('chart'),
chartOption
);
// 恢复上次选择的主题
themeSwitcher.restorePreference();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
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
⚠️ 常见问题
问题1:主题切换后配置丢失
症状:切换主题后图表配置恢复默认
原因:dispose后需要重新setOption
解决:
javascript
// ❌ 错误:只重新初始化
chart.dispose();
chart = echarts.init(dom, 'dark');
// 忘记设置option
// ✅ 正确:完整的切换流程
const currentOption = chart.getOption(); // 保存当前配置
chart.dispose();
chart = echarts.init(dom, 'dark');
chart.setOption(currentOption); // 恢复配置1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
问题2:暗色主题文字看不清
症状:暗色主题下文字与背景对比度不足
解决:
javascript
// 暗色主题下的文字配置
const darkThemeConfig = {
title: {
textStyle: {
color: '#fff' // 白色标题
}
},
legend: {
textStyle: {
color: '#ccc' // 浅灰色图例
}
},
xAxis: {
axisLabel: {
color: '#ccc' // 浅灰色刻度
},
axisLine: {
lineStyle: {
color: '#999' // 中灰色轴线
}
}
},
yAxis: {
axisLabel: {
color: '#ccc'
},
splitLine: {
lineStyle: {
color: '#444' // 深灰色分割线
}
}
},
tooltip: {
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#777',
textStyle: {
color: '#fff'
}
}
};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
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
问题3:自定义主题与内置主题冲突
症状:注册自定义主题后,内置主题失效
解决:
javascript
// ❌ 错误:覆盖全局主题
echarts.registerTheme('default', customTheme);
// ✅ 正确:使用不同的主题名称
echarts.registerTheme('myCustomTheme', customTheme);
// 使用时明确指定
const chart = echarts.init(dom, 'myCustomTheme');1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
🎯 最佳实践
1. 主题选择原则
javascript
// 数据大屏 → dark主题
const dashboardChart = echarts.init(dom, 'dark');
// 财务报告 → vintage主题
const reportChart = echarts.init(dom, 'vintage');
// 通用场景 → default主题
const normalChart = echarts.init(dom);1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
2. 响应式主题
javascript
// 根据系统主题自动切换
function getPreferredTheme() {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'default';
}
const chart = echarts.init(dom, getPreferredTheme());
// 监听系统主题变化
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
chart.dispose();
chart = echarts.init(dom, e.matches ? 'dark' : 'default');
chart.setOption(currentOption);
});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
3. 主题配置模板
javascript
// 暗色主题配置模板
const darkThemeTemplate = {
backgroundColor: '#1a1a2e',
title: {
textStyle: { color: '#fff' },
subtextStyle: { color: '#888' }
},
legend: {
textStyle: { color: '#ccc' }
},
tooltip: {
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#777',
textStyle: { color: '#fff' }
},
xAxis: {
axisLine: { lineStyle: { color: '#999' } },
axisLabel: { color: '#ccc' },
splitLine: { lineStyle: { color: '#444' } }
},
yAxis: {
axisLine: { lineStyle: { color: '#999' } },
axisLabel: { color: '#ccc' },
splitLine: { lineStyle: { color: '#444' } }
}
};
// 应用模板
chart.setOption({
...darkThemeTemplate,
// ... 其他配置
});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
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
📊 性能指标
主题对性能的影响
| 指标 | 默认主题 | dark主题 | vintage主题 |
|---|---|---|---|
| 初始化时间 | ~50ms | ~52ms | ~51ms |
| 内存占用 | 15MB | 15.2MB | 15.1MB |
| FPS | 60 | 60 | 60 |
结论:主题切换对性能影响微乎其微(<5%),可以放心使用。
🔗 相关链接
- ECharts官方主题构建工具
- 自定义主题注册
- 颜色系统配置
- 富文本样式.md)
💎 总结
内置主题核心价值:
- ✅ 快速美化:一行代码提升视觉效果
- ✅ 场景适配:不同主题适应不同场景
- ✅ 用户友好:支持系统主题自动切换
- ✅ 性能优异:几乎无性能损耗
主题选择建议:
- 数据大屏:优先使用dark主题
- 商务报告:推荐使用vintage主题
- 通用场景:使用default主题即可
下一步学习:
- 学习如何创建和注册自定义主题
- 掌握颜色系统的配置方法
- 了解富文本样式的详细用法
选择合适的主题,让你的图表更具魅力!🎨
