Three.js 工业 3D 可视化:生产线状态监控系统实现方案
在工业数字化转型过程中,3D 可视化监控系统凭借直观、沉浸式的优势,成为车间管理的重要工具。本文将详细介绍如何使用 Three.js 构建一套生产线 3D 状态监控系统,实现设备状态展示、产能数据可视化、交互式操作等核心功能
一、项目背景与技术选型
1. 项目需求
- 3D 可视化展示生产线布局及设备状态
- 实时显示生产线运行参数(产能、产量、状态等)
- 支持多生产线切换查看
- 设备状态可视化(运行 / 维护 / 停机)
- 交互式操作(视角旋转)
2. 技术栈选型
-
3D 核心库:Three.js(Web 端 3D 图形渲染引擎)
-
辅助库:
- GLTFLoader(3D 模型加载)
- OrbitControls(相机控制)
- CSS3DRenderer/CSS2DRenderer(3D/2D 标签渲染)
-
UI 框架:Element UI(进度条、样式组件)
-
动画库:animate-number(数值动画)
-
样式预处理:SCSS(样式模块化管理)
二、核心功能实现
1. 3D 场景基础搭建
场景初始化是 Three.js 项目的基础,需要完成场景、相机、渲染器三大核心对象的创建。
init() {
// 1. 创建场景
this.scene = new THREE.Scene();
// 2. 创建网格模型(生产线底座)
const geometry = new THREE.BoxGeometry(640, 1, 70);
const material = new THREE.MeshLambertMaterial({
color: 0xffffff,
transparent: true,
opacity: 1
});
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.position.set(0, -140, 0);
this.scene.add(this.mesh);
// 3. 光源设置(点光源+环境光)
const pointLight = new THREE.PointLight(0xffffff, 0.5);
pointLight.position.set(0, 200, 300);
this.scene.add(pointLight);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
this.scene.add(ambientLight);
// 4. 相机设置(正交相机,适合工业场景展示)
const container = document.getElementById("container");
const width = container.clientWidth;
const height = container.clientHeight;
const aspectRatio = width / height;
const scale = 230; // 场景显示范围系数
this.camera = new THREE.OrthographicCamera(
-scale * aspectRatio,
scale * aspectRatio,
scale,
-scale,
1,
1000
);
this.camera.position.set(-100, 100, 500);
this.camera.lookAt(this.scene.position);
// 5. 渲染器设置
this.renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
preserveDrawingBuffer: true // 保留绘制缓存
});
this.renderer.setSize(width, height);
this.renderer.setClearColor(0xffffff, 0); // 透明背景
container.appendChild(this.renderer.domElement);
// 6. 控制器设置(支持鼠标交互)
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.addEventListener("change", () => {
this.renderer.render(this.scene, this.camera);
});
// 初始渲染
this.renderer.render(this.scene, this.camera);
}
2. 3D 模型加载与生产线构建
(1)外部模型加载
使用 GLTFLoader 加载生产线设备 3D 模型(glb 格式),并设置模型位置:
loadGltf() {
const loader = new GLTFLoader();
loader.load("../model/cj.glb", (gltf) => {
gltf.scene.position.set(16, -139, 140); // 调整模型位置适配场景
this.scene.add(gltf.scene);
this.renderer.render(this.scene, this.camera);
});
}
(2)生产线围墙构建
通过 BufferGeometry 自定义几何体,创建生产线边界围墙,并用纹理贴图美化:
addWall() {
// 围墙顶点坐标
const vertices = [-320, 35, 320, 35, 320, -35, -320, -35, -320, 35];
const geometry = new THREE.BufferGeometry();
const posArr = [];
const uvArr = [];
const height = -40; // 围墙高度
// 构建围墙三角面
for (let i = 0; i < vertices.length - 2; i += 2) {
// 两个三角形组成一个矩形面
posArr.push(
vertices[i], vertices[i+1], -140,
vertices[i+2], vertices[i+3], -140,
vertices[i+2], vertices[i+3], height,
vertices[i], vertices[i+1], -140,
vertices[i+2], vertices[i+3], height,
vertices[i], vertices[i+1], height
);
// UV贴图坐标
uvArr.push(0,0, 1,0, 1,1, 0,0, 1,1, 0,1);
}
// 设置几何体属性
geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(posArr), 3);
geometry.attributes.uv = new THREE.BufferAttribute(new Float32Array(uvArr), 2);
geometry.computeVertexNormals(); // 计算法线
// 加载纹理并创建材质
this.texture = new THREE.TextureLoader().load("../images/linearGradient.png");
this.mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: this.dict_color[this.progress.state],
map: this.texture,
transparent: true,
side: THREE.DoubleSide, // 双面渲染
depthTest: false
}));
this.mesh.rotation.x = -Math.PI * 0.5; // 旋转适配场景
this.scene.add(this.mesh);
}
4. 状态可视化与数据面板
(1)多状态颜色映射
定义生产线三种状态(运行中 / 维护中 / 停机中)的颜色映射,实现状态可视化:
dict_color: {
运行中: "#32e5ad", // 绿色
维护中: "#fb8d1c", // 橙色
停机中: "#e9473a" // 红色
}
(2)数据面板设计
通过 CSS2DRenderer 将数据面板作为 2D 标签添加到 3D 场景中,实时展示生产线参数:
<div id="tooltip">
<div class="title">DIP 2-1涂覆线</div>
<div class="progress">
<p class="state">
<span class="icon" :style="{ backgroundColor: dict_color[progress.state] }"></span>
{{ progress.state }}
</p>
<p class="value">
<animate-number
from="0"
:key="progress.value"
:to="progress.value"
duration="2000"
easing="easeOutQuad"
:formatter="formatter"
></animate-number>
%
</p>
<el-progress :percentage="progress.value" :show-text="false" :color="dict_color[progress.state]"></el-progress>
</div>
<ul class="infoList">
<li v-for="(item, index) in infoList" :key="index">
<label>{{ item.label }}:</label>
<span>{{ item.value }}</span>
</li>
</ul>
</div>
addTooltip() {
const tooltipDom = document.getElementById("tooltip");
const tooltipObject = new CSS2DObject(tooltipDom);
tooltipObject.position.set(0, 120, 0); // 面板在3D场景中的位置
this.scene.add(tooltipObject);
this.labelRenderer2D.render(this.scene, this.camera);
}
5. 多生产线切换功能
支持切换查看多条生产线状态,通过点击标签切换数据和状态颜色:
changeType(index) {
this.typeIndex = index;
// 根据索引切换不同生产线的状态数据
if (index % 3 === 0) {
this.progress = this.progress1; // 运行中
} else if (index % 3 === 1) {
this.progress = this.progress2; // 维护中
} else {
this.progress = this.progress3; // 停机中
}
}
// 监听progress变化,更新3D模型颜色
watch: {
progress: {
handler() {
this.mesh.material.color.set(this.dict_color[this.progress.state]);
this.renderer.render(this.scene, this.camera);
},
deep: true
}
}
6. 响应式适配
处理窗口大小变化,确保 3D 场景自适应调整:
onWindowResize() {
const container = document.getElementById("container");
const width = container.clientWidth;
const height = container.clientHeight;
// 更新渲染器尺寸
this.renderer.setSize(width, height);
this.labelRenderer.setSize(width, height);
this.labelRenderer2D.setSize(width, height);
// 更新相机参数
const aspectRatio = width / height;
const scale = 230;
this.camera.left = -scale * aspectRatio;
this.camera.right = scale * aspectRatio;
this.camera.top = scale;
this.camera.bottom = -scale;
this.camera.updateProjectionMatrix();
// 重新渲染
this.renderer.render(this.scene, this.camera);
}
三、关键技术
1. 3D 与 2D 融合渲染
通过 CSS3DRenderer 和 CSS2DRenderer 实现 3D 场景与 2DUI 的无缝融合:
- CSS2DRenderer:用于数据面板等需要始终面向相机的 2D 元素
- CSS3DRenderer:用于生产线节点标签等需要 3D 空间定位的元素
2. 状态可视化设计
- 颜色编码:用不同颜色区分设备状态,符合工业监控的视觉习惯
- 动态更新:状态变化时实时更新 3D 模型颜色和数据面板
- 图标标识:通过图标和文字结合,增强状态辨识度
3. 性能优化
- 抗锯齿设置:提升 3D 模型显示清晰度
- 双面渲染:确保围墙等几何体正反面都能正常显示
- 纹理复用:减少重复纹理加载,提升性能
- 事件监听优化:仅在必要时重新渲染场景