threejs实现标签标注的三种方式

为了不遮挡模型的点击效果,给标签外层添加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;

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值