ECharts 是百度开源的数据可视化库,凭借丰富的图表类型和灵活的配置,成为数据大屏开发的首选方案。本文提供一套可直接使用的大屏模板,涵盖柱状图、折线图、饼图、地图、仪表盘和排名列表。

模板特点

  • 纯前端实现,无需后端即可运行
  • 深色大屏风格,开箱即用
  • CSS Grid 栅格布局,响应式适配
  • 自动轮播数据,模拟实时刷新

完整代码

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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据大屏</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0a0e17; color: #fff; font-family: 'Microsoft YaHei', sans-serif; }
.dashboard {
display: grid;
grid-template-columns: 1fr 1.5fr 1fr;
grid-template-rows: 60px 280px 280px;
gap: 12px;
padding: 12px;
height: 100vh;
}
.header {
grid-column: 1 / -1;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: bold;
letter-spacing: 8px;
background: linear-gradient(90deg, transparent, rgba(0,150,255,0.1), transparent);
}
.panel {
background: rgba(16, 22, 35, 0.9);
border: 1px solid rgba(0, 150, 255, 0.2);
border-radius: 4px;
position: relative;
}
.panel::before {
content: '';
position: absolute; top: 0; left: 0; right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, #00b4ff, transparent);
}
.chart { width: 100%; height: 100%; }
</style>
</head>
<body>
<div class="dashboard">
<div class="header">企业销售数据实时监控大屏</div>

<!-- 左上:关键指标卡片 -->
<div class="panel" id="kpi">
<div style="display:flex;justify-content:space-around;align-items:center;height:100%;padding:20px;">
<div style="text-align:center">
<div style="font-size:12px;color:#8899aa;">今日销售额</div>
<div style="font-size:32px;color:#00d4ff;font-weight:bold" id="val1">582.6万</div>
<div style="font-size:12px;color:#4caf50">↑12.3%</div>
</div>
<div style="text-align:center">
<div style="font-size:12px;color:#8899aa;">订单量</div>
<div style="font-size:32px;color:#00d4ff;font-weight:bold" id="val2">3,286</div>
<div style="font-size:12px;color:#4caf50">↑8.7%</div>
</div>
<div style="text-align:center">
<div style="font-size:12px;color:#8899aa;">客单价</div>
<div style="font-size:32px;color:#00d4ff;font-weight:bold" id="val3">1,773元</div>
<div style="font-size:12px;color:#f44336">↓2.1%</div>
</div>
</div>
</div>

<!-- 右上:饼图 -->
<div class="panel"><div class="chart" id="pie"></div></div>

<!-- 中左:柱状图 -->
<div class="panel"><div class="chart" id="bar"></div></div>

<!-- 中中:地图 -->
<div class="panel"><div class="chart" id="map"></div></div>

<!-- 中右:排名 -->
<div class="panel" id="rank" style="padding:16px;overflow-y:auto;">
<div style="font-size:14px;color:#8899aa;margin-bottom:10px;">区域销售排名</div>
<div id="rankList"></div>
</div>

<!-- 下左:折线图 -->
<div class="panel"><div class="chart" id="line"></div></div>

<!-- 下中:仪表盘 -->
<div class="panel"><div class="chart" id="gauge"></div></div>

<!-- 下右:雷达图 -->
<div class="panel"><div class="chart" id="radar"></div></div>
</div>

<script>
// ========== 通用深色主题配置 ==========
const darkTheme = {
grid: { top: 40, right: 20, bottom: 30, left: 50 },
textStyle: { color: '#8899aa', fontSize: 11 },
};

// ========== 饼图 ==========
const pie = echarts.init(document.getElementById('pie'));
pie.setOption({
...darkTheme,
title: { text: '品类销售占比', textStyle: { color: '#fff', fontSize: 14 } },
tooltip: { trigger: 'item' },
series: [{
type: 'pie', radius: ['40%', '70%'], center: ['50%', '55%'],
itemStyle: { borderRadius: 4, borderColor: '#0a0e17', borderWidth: 3 },
label: { color: '#8899aa' },
data: [
{ value: 335, name: '电子产品' },
{ value: 280, name: '家居用品' },
{ value: 210, name: '服装鞋帽' },
{ value: 156, name: '食品饮料' },
{ value: 98, name: '其他' }
]
}]
});

// ========== 柱状图 ==========
const bar = echarts.init(document.getElementById('bar'));
bar.setOption({
...darkTheme,
title: { text: '各区域月度销售', textStyle: { color: '#fff', fontSize: 14 } },
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: ['华东','华南','华北','华中','西南','西北','东北'], axisLabel: { color: '#8899aa' } },
yAxis: { type: 'value', splitLine: { lineStyle: { color: 'rgba(255,255,255,0.06)' } }, axisLabel: { color: '#8899aa' } },
series: [{
type: 'bar', data: [820, 690, 560, 430, 380, 250, 180],
itemStyle: { borderRadius: [4,4,0,0], color: new echarts.graphic.LinearGradient(0,0,0,1,[
{ offset:0, color:'#00d4ff' }, { offset:1, color:'#0066aa' }
]) },
barWidth: '50%'
}]
});

// ========== 折线图(趋势) ==========
const line = echarts.init(document.getElementById('line'));
const months = ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'];
line.setOption({
...darkTheme,
title: { text: '年度销售趋势', textStyle: { color: '#fff', fontSize: 14 } },
tooltip: { trigger: 'axis' },
legend: { data: ['本年','去年'], textStyle: { color: '#8899aa' }, top: 5 },
xAxis: { type: 'category', data: months, axisLabel: { color: '#8899aa' } },
yAxis: { type: 'value', splitLine: { lineStyle: { color: 'rgba(255,255,255,0.06)' } }, axisLabel: { color: '#8899aa' } },
series: [
{ name: '本年', type: 'line', smooth: true, data: [420,480,550,620,580,710,780,850,820,890,950,1020], lineStyle:{color:'#00d4ff'}, itemStyle:{color:'#00d4ff'}, areaStyle:{color:'rgba(0,212,255,0.1)'} },
{ name: '去年', type: 'line', smooth: true, data: [380,400,450,480,500,550,580,620,600,650,700,750], lineStyle:{color:'#ff6b6b',type:'dashed'}, itemStyle:{color:'#ff6b6b'} }
]
});

// ========== 地图 ==========
const map = echarts.init(document.getElementById('map'));
map.setOption({
...darkTheme,
title: { text: '全国销售分布', textStyle: { color: '#fff', fontSize: 14 } },
tooltip: { trigger: 'item' },
visualMap: { min:0, max:1000, left:'left', top:'bottom', text:['高','低'], textStyle:{color:'#8899aa'}, inRange:{color:['#0a1628','#0d3b66','#1a7fb5','#00d4ff']}, calculable:false },
series: [{
type: 'map', map: 'china', roam: false,
itemStyle: { borderColor: 'rgba(100,200,255,0.3)', borderWidth: 1, areaColor: '#0d2137' },
emphasis: { label:{show:true,color:'#fff'}, itemStyle:{areaColor:'#0066aa'} },
data: [
{name:'广东',value:920},{name:'江苏',value:810},{name:'浙江',value:760},
{name:'山东',value:680},{name:'河南',value:520},{name:'四川',value:480},
{name:'湖北',value:430},{name:'湖南',value:380},{name:'北京',value:560},
{name:'上海',value:620},{name:'福建',value:390},{name:'安徽',value:350}
]
}]
});

// ========== 仪表盘 ==========
const gauge = echarts.init(document.getElementById('gauge'));
gauge.setOption({
title: { text: '目标完成率', textStyle: { color: '#fff', fontSize: 14 }, left: 'center' },
series: [{
type: 'gauge', center: ['50%', '58%'], radius: '80%',
startAngle: 210, endAngle: -30,
min: 0, max: 100,
axisLine: { lineStyle: { width: 18, color: [[0.3,'#00d4ff'],[0.7,'#1a7fb5'],[1,'#0d3b66']] } },
axisTick: { show: false }, splitLine: { show: false }, axisLabel: { show: false },
pointer: { length:'60%', width:6, itemStyle:{color:'#00d4ff'} },
detail: { valueAnimation: true, fontSize: 28, color: '#fff', offsetCenter: [0,'60%'] },
data: [{ value: 78.5, name: '%' }]
}]
});

// ========== 雷达图 ==========
const radar = echarts.init(document.getElementById('radar'));
radar.setOption({
...darkTheme,
title: { text: '各维度评分雷达', textStyle: { color: '#fff', fontSize: 14 } },
radar: {
center: ['50%', '55%'], radius: '65%',
indicator: [
{ name:'销售额', max:100 }, { name:'利润率', max:100 }, { name:'客户数', max:100 },
{ name:'复购率', max:100 }, { name:'满意度', max:100 }, { name:'覆盖区域', max:100 }
],
axisName: { color: '#8899aa' },
splitArea: { areaStyle: { color: ['rgba(0,180,255,0.02)','rgba(0,180,255,0.05)'] } },
splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
},
series: [{
type: 'radar',
data: [{ value: [85, 72, 90, 65, 88, 78], name: '当前', areaStyle:{color:'rgba(0,212,255,0.2)'}, lineStyle:{color:'#00d4ff'}, itemStyle:{color:'#00d4ff'} }],
symbol: 'circle', symbolSize: 4
}]
});

// ========== 排名列表 ==========
const rankData = [
{ name:'华东', value:820, trend:'up' },
{ name:'华南', value:690, trend:'up' },
{ name:'华中', value:560, trend:'down' },
{ name:'华北', value:510, trend:'up' },
{ name:'西南', value:430, trend:'down' },
{ name:'西北', value:380, trend:'up' },
{ name:'东北', value:250, trend:'down' },
];
const rankHtml = rankData.map((d, i) => `
<div style="display:flex;align-items:center;padding:8px 0;border-bottom:1px solid rgba(255,255,255,0.05);">
<span style="width:24px;height:24px;line-height:24px;text-align:center;border-radius:50%;font-size:12px;
background:${i<3?'#00d4ff':'#1a3a5c'};color:${i<3?'#000':'#8899aa'};margin-right:12px;">${i+1}</span>
<span style="flex:1;">${d.name}</span>
<span style="font-weight:bold;margin-right:8px;">${d.value}万</span>
<span style="color:${d.trend==='up'?'#4caf50':'#f44336'}">${d.trend==='up'?'↑':'↓'}</span>
</div>
`).join('');
document.getElementById('rankList').innerHTML = rankHtml;

// ========== 响应式 ==========
window.addEventListener('resize', () => {
[pie, bar, line, map, gauge, radar].forEach(chart => chart.resize());
});
</script>
</body>
</html>

核心知识点

响应式栅格布局

1
2
3
4
5
6
7
.dashboard {
display: grid;
grid-template-columns: 1fr 1.5fr 1fr; /* 左栏 : 中栏 : 右栏 */
grid-template-rows: 60px 280px 280px; /* 标题行 + 两行图表 */
gap: 12px;
height: 100vh;
}

使用 CSS Grid 轻松实现大屏常见的「三栏+多层」布局,grid-column: 1 / -1 让标题栏跨整行。

图表配色技巧

深色大屏的核心配色原则:低饱和背景 + 高亮数据色。统一使用 #00d4ff(青蓝)作为主色调,配合 rgba(0,212,255,0.x) 透明度变化形成层次。

地图数据注册

ECharts 5 需要单独引入中国地图或使用在线 GeoJSON:

1
2
3
4
5
6
7
8
9
<!-- 方式一:CDN 引入(推荐) -->
<script src="https://geo.datav.aliyun.com/areas_v3/bound/100000_full.js"></script>

<!-- 方式二:registerMap 注册本地 GeoJSON -->
<script>
fetch('/assets/china.json')
.then(res => res.json())
.then(geo => echarts.registerMap('china', geo));
</script>

将上述代码保存为 .html 文件即可直接在浏览器中打开,修改其中的模拟数据替换为真实 API 即可接入实际业务。