为了不遮挡模型的点击效果,给标签外层添加pointer-events :none
对比
CSS2DRenderer
大小是固定的
,始终正面朝向我们的相机。
自己写代码把世界坐标xyz,转化为像素px表示屏幕坐标,比较麻烦,不过threejs扩展库CSS2DRenderer.js可以帮助你实现坐标转化,给HTML元素标签定位,下面给大家演示如何实现。
CSS2DObject
:css2模型对象
CSS2DRenderer
:css2模型渲染器
import {
CSS2DObject, CSS2DRenderer
} from "three/examples/jsm/renderers/CSS2DRenderer";
//一、创建模型渲染器
// 创建一个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);
//二、在resize方法中,记得也要写渲染器的更新
this.labelRenderer.setSize(window.innerWidth, window.innerHeight)
//三、animation中
labelRenderer.render(scene, camera); //渲染HTML标签对象
//四、创建css2模型对象
const div = document.getElementById('tag');
div.style.top = '-161px'; //指示线端点和标注点重合
// HTML元素转化为threejs的CSS2模型对象
const tag= new CSS2DObject(div);
tag.position.set(worldPosition.x, worldPosition.y, worldPosition.z - 10)
tag.element.style.display = 'block'
tag.element.style.left = e.offsetX - 100 + 'px'
tag.element.style.top = e.offsetY - 164 + 'px'
CSS3DRenderer
CSS3DObject和CSS3DSprite 都需要先有CSS3DRenderer
,CSS3DRenderer的创建跟CSS2DRenderer类似
初始化操作:
initD3() {
// 创建一个CSS3渲染器CSS3DRenderer
this.D3Render = new CSS3DRenderer();
this.D3Render.setSize(this.width, this.height);
// HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合
this.D3Render.domElement.style.position = "absolute";
this.D3Render.domElement.style.top = "0px";
//设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
this.D3Render.domElement.style.pointerEvents = "none";
const containerDom = document.getElementById(this.id);
containerDom.appendChild(this.D3Render.domElement);
}
//在resize
this.D3Render.setSize(innerWidth, innerHeight);
//在animation
this.D3Render.render(this.scene, this.camera);
CSS3DObject
可以通过相机控件OrbitControls旋转、缩放三维场景,CSS3模型对象CSS3DObject跟着旋转、缩放,但是旋转的时候背面是一个对称的效果。
比如下面就是旋转后的效果
- 可以禁止展示对应HTMK元素背面展示
<div id="tag" style="backface-visibility: hidden;">标签内容</div>
实际创建:
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3模型对象
const tag = new CSS3DObject(div);
//标签tag作为mesh子对象,默认标注在模型局部坐标系坐标原点
const geometry = new THREE.ConeGeometry(25, 80);
geometry.translate(0, 40, 0);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
});
const mesh = new THREE.Mesh(geometry, material);
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥顶部
tag.position.y += 80;
this.viewer.scene.add(mesh)
CSS3DSprite
CSS3精灵模型CSS3DSprite对应的HTML标签,可以跟着场景缩放,位置可以跟着场景旋转,但是自身的姿态角度始终平行于canvas画布
,不受旋转影响,就像精灵模型一样Sprite
const div = document.getElementById('tag');
// HTML元素转化为threejs的CSS3模型对象
const tag = new CSS3DSprite(div);
//标签tag作为mesh子对象,默认标注在模型局部坐标系坐标原点
const geometry = new THREE.ConeGeometry(25, 80);
geometry.translate(0, 40, 0);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
});
const mesh = new THREE.Mesh(geometry, material);
mesh.add(tag);
// 相对父对象局部坐标原点偏移80,刚好标注在圆锥顶部
tag.position.y += 80;
this.viewer.scene.add(mesh)
精灵模型Sprite
精灵模型渲染Sprite的标签,默认可以被其他网格模型遮挡
,但是CSS3渲染器渲染
的HTML元素标签是叠加
在canvas画布上,不会被其它网格模型遮挡。
import * as THREE from 'three';
// 标注位置对应的模型对象obj
function createSprite(obj,state) {
const texLoader= new THREE.TextureLoader();
let texture = null;
if(state == '警告'){
texture= texLoader.load("./警告.png");
}else{
texture = texLoader.load("./故障.png");
}
const spriteMaterial = new THREE.SpriteMaterial({
map: texture,
});
const sprite = new THREE.Sprite(spriteMaterial);
// 控制精灵大小
sprite.scale.set(5, 5, 1);
sprite.position.y = 5 / 2; //标签底部箭头和空对象标注点重合
obj.add(sprite); //tag会标注在空对象obj对应的位置
}
export default createSprite;