CSS2D面向摄像机,场景缩放时,缩小放大都一样大,不被模型遮挡,通过DOM事件点击
在模型中添加CSS2DRenderer标注,在之前的项目中也遇到了一个这样的需求,自己研究了好长时间也没搞出来,最后购买了教程跟着教程走了一遍才理解了实现方法。
使用的threejs版本号0.123.0,不同的版本的api可能有差异。
CSS2DRenderer是CSS3DRenderer(CSS 3D渲染器)的简化版本,唯一支持的变换是位移。
如果你希望将三维物体和基于HTML的标签相结合,则这一渲染器将十分有用。在这里,各个DOM元素也被包含到一个CSS2DObject实例中,并被添加到场景图中。
效果演示
实际项目中运用效果
创建标签
首先创建标签,将我们的标签方法写出来,在添加标注前需要先给模型命名
function tag(name) {
// 创建div元素(作为标签)
var div = document.createElement('div');
div.innerHTML = name;
div.classList.add('tag');
//div元素包装为CSS2模型对象CSS2DObject
var label = new CSS2DObject(div);
div.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件
// 设置HTML元素标签在three.js世界坐标中位置
// label.position.set(x, y, z);
return label;//返回CSS2模型标签
}
// 创建一个CSS2渲染器CSS2DRenderer
var labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
// 相对标签原位置位置偏移大小
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.left = '0px';
// //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
labelRenderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(labelRenderer.domElement);
查找模型
在模型中查找遍历模型使用getWorldPosition
获取世界坐标将坐标赋予标签显示
var group = gltf.scene.getObjectByName('粮仓');
// console.log('粮仓', group);
group.traverse(function (obj) {
if (obj.type === 'Mesh') {
var label = tag(obj.name);//把粮仓名称obj.name作为标签
var pos = new THREE.Vector3();
obj.getWorldPosition(pos);//获取obj世界坐标、
// 粮仓世界坐标对应粮仓底部圆心位置,如果标签像标注在粮仓底部,需要加上粮仓整体高度
label.position.copy(pos);//标签标注在obj世界坐标
model.add(label);//标签插入model组对象中
}
})
渲染标签
import { labelRenderer } from './scene/tag.js';//HTML标签相关代码
// 渲染循环
function render() {
labelRenderer.render(scene, camera); //渲染HTML标签对象
renderer.render(scene, camera); //执行渲染操作
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
// console.log(camera.position);//通过相机控件OrbitControls旋转相机,选择一个合适场景渲染角度
}
render();
视频教程地址
threejs实现css2d的相关视频教程:使用CSS2DRenderer标注每个粮仓
实例代码
项目环境基于vue3 vite js node.js 14