ThreeJS教程:CSS3批量标注多个标签
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
CSS3批量标注多个标签
下面下工厂为例,使用CSS3DRenderer批量渲染多个HTML元素标签。
CSS3渲染器基本代码
CSS3渲染器代码和上节课内容一样设置即可。
// 引入CSS3渲染器CSS3DRenderer
import {CSS3DRenderer} from 'three/addons/renderers/CSS3DRenderer.js';
// 创建一个CSS3渲染器CSS3DRenderer
const css3Renderer = new CSS2DRenderer();
css3Renderer.setSize(width, height);
// HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合
css3Renderer.domElement.style.position = 'absolute';
css3Renderer.domElement.style.top = '0px';
//设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
css3Renderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(css3Renderer.domElement);
// 渲染循环
function render() {
css3Renderer.render(scene, camera);
// ...
requestAnimationFrame(render);
}
window.onresize = function () {
...
// HTML标签css3Renderer.domElement尺寸重新设置
css3Renderer.setSize(width,height);
};
标签HTML、CSS代码
使用了一个带有箭头的背景图png图片。
<style>
#tag {
width: 70px;
height: 40px;
line-height: 32px;
text-align: center;
color: #fff;
font-size: 16px;
background-image: url(./标签箭头背景.png);
background-repeat: no-repeat;
background-size: 100% 100%;
}
</style>
<div id="tag">设备A</div>
HTML标签渲染前隐藏
在CSS3渲染器渲染HTML标签,重新定位标签之前,可以先把标签隐藏display: none;
。
<div id="tag" style="display: none;">设备A</div>
三维软件中设置需要标注的位置
在需要标注的位置,可以创建多个空对象,用来给CSS3标签模型定位。
工厂模型中分别命名了三个空对象设备A标注、设备B标注、停车场标注。
创建CSS3模型对象或精灵对象标注场景
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3对象
// const tag = new CSS3DObject(div);
const tag = new CSS3DSprite(div);
div.style.pointerEvents = 'none';//避免标签遮挡canvas鼠标事件
// obj是建模软件中创建的一个空对象
const obj = gltf.scene.getObjectByName('设备A标注');
//tag会标注在空对象obj对应的位置
obj.add(tag);
模型缩放
设置CSS3模型或精灵对象尺寸的时候,你就把他想象为一个普通矩形平面网格模型Mesh,CSS3模型或精灵的尺寸来自自身HTML元素的尺寸像素值。
HTML标签元素的高度是几十个像素,工厂尺寸是100多,整体预览工厂模型的时候,如果标签覆盖区域过大,你可以适当缩小。
// const tag = new CSS3DObject(div);
const tag = new CSS3DSprite(div);
//适当缩放模型标签
tag.scale.set(0.1,0.1,1);
模型定位
把模型标签背景的箭头放在空对象标注点的附近位置,根据HTML标签的几何中心与标签箭头的top、left差值来设置即可,注意如果缩放了标签模型,还要考虑缩放的问题。
注意不同标签top、left差值,可能不同,该案例只有top方向偏差是高度一半(注意height、border、padding的影响)。
tag.scale.set(0.1,0.1,1);
//标签底部箭头和空对象标注点重合:偏移高度像素值一半*缩放比例
tag.position.y = 40/2*0.1;
批量创建标签
如果是Vue或React批量创建UI组件还是比较方便的,原生HTML、CSS的话,注意批量创建DOM即可,原理一样。
//需要批量标注的标签数据arr
const arr = ['设备A','设备B','停车场'];
for (let i = 0; i < arr.length; i++) {
// 注意是多个标签,需要克隆复制一份
const div = document.getElementById('tag').cloneNode();
div.innerHTML = arr[i];//标签数据填写
// HTML元素转化为threejs的CSS3对象
// const tag = new CSS3DObject(div);
const tag = new CSS3DSprite(div);
div.style.pointerEvents = 'none'; //避免标签遮挡canvas鼠标事件
// obj是建模软件中创建的一个空对象
const obj = gltf.scene.getObjectByName(arr[i]+'标注');
//tag会标注在空对象obj对应的位置
obj.add(tag);
tag.scale.set(0.1,0.1,1);//适当缩放模型标签
tag.position.y = 40/2*0.1;//标签底部箭头和空对象标注点重合:偏移高度像素值一半*缩放比例
}