郭隆邦老师threejs教程学习笔记
在Threejs项目中,通过HTML元素来创建一个UI界面作为模型标签来显示相关信息还是比较方便的。比如一个3D可视化粮仓项目中,通过HTML元创建一个表格窗口悬浮在三维场景模型上,表示一个该模型对应粮仓的温度、湿度、吨位等信息。
HTML元素表示模型标签
通过HTML标签和CSS创建一个UI界面,作为模型的标签可以显示模型对应的信息,下面的UI界面效果是简单编写的,实际项目中,可以根据UI的设计效果写一个很精美的标签来表示模型的信息。
/**
* 创建div元素,并输入一串文字表示模型信息(作为立方体标签)
*/
const div = document.createElement('div');
div.innerHTML = name;
div.style.padding = '10px';
div.style.color = '#fff';
div.style.position = 'absolute';
div.style.backgroundColor = 'rgba(25,25,25,0.5)';
div.style.borderRadius = '5px'
document.body.appendChild(div);
计算模型标签位置
通过三维向量对象Vector3
方法.project()
的计算世界坐标worldVector在camera相机对象矩阵变化下对应的标准设备坐标, 标准WebGL设备坐标xyz的范围是[-1,1]。
关于.project()
方法的解释可以参考官方文档,.project ()
方法是通过相机对象的视图矩阵和投影矩阵对三维向量Vector3
表示的坐标进行投影变换。
因为canvas画布是全屏状态,完全填充浏览器窗口的客户区,canvas画布的宽高尺寸就是window.innerWidth、window.innerHeight。 画布的中心从屏幕坐标系的角度看是坐标是(window.innerWidth/2,window.innerHeight/2),从WebGL标准设备坐标系的角度看是坐标原点(0,0). 对于初次接触WebGL的读者,如果不太清楚世界坐标系、屏幕坐标系、标准设备坐标系的区别可以不用深入理解,直接复制下面的代码会修改即可。
// 网格模型在threejs三维空间的世界坐标
const worldVector = mesh.position.clone();
//世界坐标转标准设备坐标,standardVector是WebGL标准设备坐标
// .project()方法提取相机参数的视图矩阵、投影矩阵对世界坐标进行变换
const standardVector = worldVector.project(camera);
// 根据WebGL标准设备坐标standardVector计算div标签在浏览器页面的屏幕坐标
// 标准设备坐标转屏幕坐标 可以参照下图理解转换公式
const a = window.innerWidth / 2;
const b = window.innerHeight / 2;
const x = Math.round(standardVector.x * a + a); //模型标签x坐标,单位像素
const y = Math.round(-standardVector.y * b + b); //模型标签y坐标,单位像素
定位模型标签(HTML元素)位置
根据坐标变换计算的模型标签位置数据来设置标签元素的.style.left
和.style.top
属性
/**
* 设置标签元素的位置
*/
div.style.left = x + 'px';
//这里的130px主要是为了标签和模型有一定偏移,当然也可以不设置,两者叠加在一起
div.style.top = y - 130 + 'px';
模型标签位置测试
你可以把网格模型boxMesh
在场景中设置在不同的位置,查看标签是否跟着模型移动。
const boxMesh = new THREE.Mesh(...);
// 网格模型设置不同的位置,标签显示在对应的位置
boxMesh.position.set(80, 0, 0);
// boxMesh.position.set(0, 100, 0);
// boxMesh.position.set(0, 0, 50);
复杂模型标签
对于简单的模型标签可通过常见的div、table等HTMl元素实现,如果形状比较复杂的UI界面也可以使用SVG、Canvas等2D绘制技术实现。