跳到主要内容
基于 ECharts 与 Three.js 的碳排放可视化大屏实现 | 极客日志
JavaScript 大前端
基于 ECharts 与 Three.js 的碳排放可视化大屏实现 综述由AI生成 展示了一个基于 ECharts 和 Three.js 构建的碳排放可视化大屏项目。核心功能包括多模块图表切换(教室、实验室、宿舍)、3D 地球动画展示以及响应式布局设计。代码涵盖了 HTML 结构、CSS 样式适配及 JavaScript 交互逻辑,适合前端开发者参考学习大屏开发流程。
落日余晖 发布于 2026/4/8 更新于 2026/5/3 5 浏览前端可视化大屏实战:碳排放数据展示
效果预览
项目最终呈现为一个响应式的大屏界面,包含左侧、中间和右侧三个主要区域。中间核心位置展示 3D 地球模型及关键指标,两侧分布各类统计图表。整体采用深色科技风背景,支持动态切换不同场景(如教室、实验室、宿舍)的数据视图。
技术架构概览
本项目主要依赖以下技术栈:
HTML/CSS : 负责页面骨架与样式布局,使用 Flexbox 实现三栏结构。
JavaScript (ES6+) : 核心交互逻辑,处理图表渲染与事件监听。
ECharts : 用于绘制柱状图、折线图、饼图等常规统计图表。
Three.js : 用于构建中间的 3D 地球动画效果。
Jinja2 : 模板引擎(从 url_for 推断),用于资源路径管理。
核心代码解析
1. 页面结构与资源引入 (view.html)
页面主体分为 Header、Section 和 Footer 三部分。Header 显示标题与实时时间,Section 内部通过 .column 类划分左中右三列。值得注意的是,我们使用了 flexible.js 来适配不同分辨率的设备,确保在大屏上比例协调。
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > Title</title >
<link rel ="stylesheet" href ="{{ url_for('static', filename='css/view.css') }}" >
</head >
<body >
<header >
碳排放可视化大屏
教室
实验室
宿舍
教室
实验室
宿舍
早
晚
<div class ="container" >
<h1 >
</h1 >
</div >
<div class ="showTime" >
</div >
<script >
var t = null ;
t = setTimeout (time, 1000 );
function time ( ) {
clearTimeout (t);
var a = new Date ();
var y = a.getFullYear ();
var mt = a.getMonth () + 1 ;
var day = a.getDate ();
var h = a.getHours ();
var m = a.getMinutes ();
var s = a.getSeconds ();
document .querySelector (".showTime" ).innerHTML = '当前时间:' + y + "年" + mt + "月" + day + "-" + h + "时" + m + "分" + s + "秒" ;
t = setTimeout (time, 1000 );
}
</script >
</header >
<section class ="box" >
<div class ="column" >
<div class ="public bar right-chart-module" >
<div class ="chart-title" >
<h2 >
</h2 >
<div class ="chart-tabs" >
<button class ="tab-btn active" data-type ="classroom" >
</button >
<button class ="tab-btn" data-type ="lab" >
</button >
<button class ="tab-btn" data-type ="dormitory" >
</button >
</div >
</div >
<div class ="char" id ="leftBarChart" >
</div >
<div class ="public-one" >
</div >
</div >
</div >
<div class ="column" >
<div class ="num" >
<div class ="globe-container" >
<canvas id ="globe-canvas" >
</canvas >
</div >
</div >
</div >
<div class ="column" >
<div class ="public bar right-chart-module" >
<div class ="chart-title" >
<h2 >
</h2 >
<div class ="chart-tabs" >
<button class ="tab-btn active" data-type ="classroom" >
</button >
<button class ="tab-btn" data-type ="lab" >
</button >
<button class ="tab-btn" data-type ="dormitory" >
</button >
</div >
</div >
<div class ="char" id ="vehicleChart" >
</div >
<div class ="public-one" >
</div >
</div >
<div class ="public pie" >
<div class ="chart-title" >
<h2 >
</h2 >
<div class ="chart-tabs" >
<button class ="tab-btn active" data-time ="morning" >
</button >
<button class ="tab-btn" data-time ="evening" >
</button >
</div >
</div >
<div class ="char" id ="pieChart" >
</div >
<div class ="public-one" >
</div >
</div >
</div >
</section >
<script src ="{{ url_for('static', filename='js/echarts.js') }}" >
</script >
<script src ="{{ url_for('static', filename='js/echarts.min.js') }}" >
</script >
<script src ="{{ url_for('static', filename='js/view.js') }}" >
</script >
<script src ="{{ url_for('static', filename='js/flexible.js') }}" >
</script >
<script src ="{{ url_for('static', filename='js/jiazai.js') }}" >
</script >
<script >
document .addEventListener ('DOMContentLoaded' , () => {
setTimeout (() => window .dispatchEvent (new Event ('resize' )), 300 );
});
</script >
</body >
</html >
2. 样式适配与布局 (view.css) 样式部分采用了 Rem 单位配合 flexible.js 进行自适应。背景图设置为固定定位,避免滚动时闪烁。图表容器使用了半透明边框和四角装饰,增强科技感。特别需要注意的是媒体查询部分,针对不同屏幕宽度调整了字体大小,保证移动端也能查看。
* { margin : 0 ; padding : 0 ; box-sizing : border-box; }
li { list-style : none; }
@font-face { font-family : electronicFont; src : url (/static/font/ziti.TTF ); }
html { font-size : 100px ; overflow : hidden; width : 100% ; height : 100% ; }
body {
font-family : Arial, Helvetica, sans-serif;
background : url (/static/images/bei.jpg ) no-repeat;
background-size : cover;
background-attachment : fixed;
line-height : 1.15 ;
width : 100% ;
height : 100% ;
overflow : hidden;
}
header {
position : relative;
height : 1.11rem ;
background : url (/static/images/head.png ) no-repeat top center;
background-size : 100% 100% ;
width : 100% ;
}
header .container h1 {
font-size : 0.51rem ;
color : #fff ;
text-align : center;
line-height : 1.07rem ;
-webkit-text -stroke : 2px #00f7ff ;
text-shadow : 0 0 10px rgba (0 , 247 , 255 , 0.5 );
}
.box { display : flex; min-width : 1024px ; max-width : 1920px ; width : 100% ; height : calc (100% - 1.11rem ); margin : 0 auto; padding : 0.13rem ; overflow : hidden; }
.box .column { flex : 3 ; height : 100% ; display : flex; flex-direction : column; }
.box .column :nth-child (2 ) { flex : 5 ; margin : 0 0.13rem ; }
@media screen and (max-width : 1024px ) { html { font-size : 42px !important ; } }
@media screen and (min-width : 1920px ) { html { font-size : 80px !important ; } }
3. 图表交互逻辑 (view.js) JS 文件是核心所在,我们将不同图表封装在 IIFE 中以避免污染全局变量。每个图表模块都配置了独立的数据源,并通过 Tab 按钮触发 updateChart 函数来切换数据。
以柱状图为例,我们定义了 chartData 对象存储不同场景(教室、实验室、宿舍)的用电量数据。当用户点击 Tab 时,移除旧激活状态,更新当前类型并重新渲染 ECharts 实例。同时监听了 window.resize 事件,确保窗口缩放时图表自动适应。
(function ( ){
const chartData = {
classroom : { title : '教室每日用电量统计' , data : { categories : ['周一' ,'周二' ,'周三' ,'周四' ,'周五' ,'周六' ,'周日' ], series : [{ name :'早' , data :[6.28 ,9.55 ,8.69 ,8.63 ,6.64 ,4.17 ,2.69 ] }, { name :'晚' , data :[5.71 ,8.65 ,5.32 ,5.91 ,5.77 ,3.17 ,1.85 ]} ] }, colors :['#5470C6' ,'#91CC75' ] },
lab : { title : '实验室每日用电量统计' , data : { categories : ['周一' ,'周二' ,'周三' ,'周四' ,'周五' ,'周六' ,'周日' ], series : [{ name :'早' , data :[13.85 ,17.78 ,20.12 ,16.77 ,14.69 ,3.46 ,5.72 ] }, { name :'晚' , data :[9.05 ,11.72 ,14.37 ,11.42 ,11.62 ,3.17 ,5.63 ]} ] }, colors :['#EE6666' ,'#FAC858' ] },
dormitory : { title : '宿舍每日用电量统计' , data : { categories : ['周一' ,'周二' ,'周三' ,'周四' ,'周五' ,'周六' ,'周日' ], series : [{ name :'早' , data :[4.23 ,3.98 ,4.56 ,4.01 ,4.34 ,2.78 ,2.45 ] }, { name :'晚' , data :[5.31 ,5.45 ,5.12 ,5.78 ,6.89 ,7.01 ,5.67 ]} ] }, colors :['#73C0DE' ,'#3BA272' ] }
};
document .addEventListener ('DOMContentLoaded' , function ( ){
var barChartDom = document .querySelector ('.bar .char' );
var titleElement = document .querySelector ('.bar .chart-title h2' );
var tabButtons = document .querySelectorAll ('.bar .tab-btn' );
if (barChartDom && titleElement && tabButtons.length >0 ){
var barChart = echarts.init (barChartDom);
var currentType = 'classroom' ;
function updateChart (type ){
const data = chartData[type].data ;
const colors = chartData[type].colors ;
const barOption = {
color : colors,
title : { text : chartData[type].title , left :'center' , textStyle :{fontSize :16 ,color :'#fff' }, top :-3 },
tooltip : { trigger :'axis' , axisPointer :{type :'shadow' } },
legend : { data :['早' ,'晚' ], textStyle :{color :'#fff' }, top :20 },
grid : { top :'20%' , left :'3%' , right :'4%' , bottom :'3%' , containLabel :true },
xAxis : { type :'category' , data : data.categories , axisLine :{lineStyle :{color :'#fff' }}, axisLabel :{color :'#fff' ,interval :0 } },
yAxis : { type :'value' , name :'用电量 (千瓦)' , nameTextStyle :{color :'#fff' ,padding :[0 ,0 ,0 ,30 ]}, axisLine :{show :true ,lineStyle :{color :'#fff' }}, axisLabel :{color :'#fff' }, splitLine :{lineStyle :{color :'rgba(255, 255, 255, 0.2)' }} },
series : [
{name :'早' ,type :'bar' ,barWidth :'30%' ,barGap :'50%' ,data : data.series [0 ].data ,},
{name :'晚' ,type :'bar' ,barWidth :'30%' ,data : data.series [1 ].data ,}
]
};
barChart.setOption (barOption);
}
updateChart (currentType);
tabButtons.forEach (button => {
button.addEventListener ('click' ,function ( ){
tabButtons.forEach (btn => btn.classList .remove ('active' ));
this .classList .add ('active' );
currentType = this .dataset .type ;
updateChart (currentType);
});
});
window .addEventListener ('resize' ,function ( ){ barChart.resize (); });
}
});
})();
4. 3D 地球动画 (initGlobe) 中间区域的地球使用了 Three.js 构建。我们通过加载纹理贴图(法线贴图、高光贴图)来增加真实感。光照系统包含环境光和方向光,模拟自然光照效果。动画循环中不断旋转地球 Mesh,营造动态视觉体验。
function initGlobe ( ){
const scene = new THREE .Scene ();
const camera = new THREE .PerspectiveCamera (75 , 1 , 0.1 , 1000 );
const renderer = new THREE .WebGLRenderer ({ canvas : document .getElementById ('globe-canvas' ), antialias : true , alpha : true });
renderer.setSize (400 , 300 );
renderer.setClearColor (0x000000 , 0 );
const geometry = new THREE .SphereGeometry (5 , 64 , 64 );
const material = new THREE .MeshPhongMaterial ({
color : 0x156289 , emissive : 0x072534 , shininess : 5 , transparent : true , opacity : 0.8 , wireframe : false
});
const textureLoader = new THREE .TextureLoader ();
material.map = textureLoader.load ('/static/images/img.png' );
material.bumpMap = textureLoader.load ('https://threejs.org/examples/textures/planets/earth_normal_2048.jpg' );
material.specularMap = textureLoader.load ('https://threejs.org/examples/textures/planets/earth_specular_2048.jpg' );
const earth = new THREE .Mesh (geometry, material);
scene.add (earth);
const ambientLight = new THREE .AmbientLight (0x333333 );
scene.add (ambientLight);
const directionalLight = new THREE .DirectionalLight (0xffffff , 1 );
directionalLight.position .set (5 , 3 , 5 );
scene.add (directionalLight);
camera.position .z = 12 ;
function animate ( ){
requestAnimationFrame (animate);
earth.rotation .y += 0.002 ;
renderer.render (scene, camera);
}
animate ();
function resizeGlobe ( ){
const container = document .querySelector ('.globe-container' );
const width = container.clientWidth ;
const height = container.clientHeight ;
camera.aspect = width / height;
camera.updateProjectionMatrix ();
renderer.setSize (width, height);
}
window .addEventListener ('resize' , resizeGlobe);
resizeGlobe ();
}
if (typeof THREE === 'undefined' ){
const script = document .createElement ('script' );
script.src = 'https://cdn.jsdelivr.net/npm/[email protected] /build/three.min.js' ;
script.onload = initGlobe;
document .head .appendChild (script);
}else {
initGlobe ();
}
5. 辅助工具 项目中还包含了 jiazai.js 用于处理资源加载缓存问题,以及 flexible.js 用于计算 Rem 基准值,确保在不同设备上的布局一致性。这些工具函数虽然不起眼,但对大屏项目的稳定性至关重要。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online