[ThreeJs] How to label the model with text?

I. Overview

The grid model created in ThreeJs rendering, sometimes we need to add label text to the model to facilitate the identification of different objects. At this time ,
we can use these two libraries, which provide three ways of labeling. As the camera angle changes, the display effects of the three labels are different. The three tags are: CSS 2DObject, CSS 3DObject tag, CSS 3DSprite tagCSS3DRendererCSS2DRenderer

2. Effect preview

1. Different angles

Here's how the same set of models looks when viewed from different angles:
insert image description here

2. The distance is different

This is how the two sets of models look before and after:
insert image description here

3. Brief description of the difference

It can be seen that , CSS 2DObjectand CSS 3DSpritecan make the label always face the current camera angle of view. The difference is that the size of the label will not be affected by the distance CSS 2DObject; Labels are all realized by using , and the size of the label will also be affected by the distance, the far is smaller and the near is bigger.CSS 3DSprite
CSS 3DObjecthtml+cssCSS 3DObject

3. Code implementation

tag2D.js【Create CSS2DObject】

import {
    
     CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
// 创建一个HTML标签
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
function labelRenderer(container) {
    
    
  var labelRenderer = new CSS2DRenderer();
  labelRenderer.setSize(container.offsetWidth, container.offsetHeight);
  labelRenderer.domElement.style.position = 'absolute';
  // 相对标签原位置位置偏移大小
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.left = '0px';
  // //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
  labelRenderer.domElement.style.pointerEvents = 'none';
  container.appendChild(labelRenderer.domElement);
  return labelRenderer;
}

export {
    
     tag, labelRenderer }

tag3D.js【Create CSS3DObject, CSS3DSprite】

import {
    
     CSS3DRenderer, CSS3DObject ,CSS3DSprite} from 'three/examples/jsm/renderers/CSS3DRenderer.js';
// 创建一个HTML标签
function tag3D(name) {
    
    
  // 创建div元素(作为标签)
  var div = document.createElement('div');
  div.innerHTML = name;
  div.classList.add('tag');
  //div元素包装为CSS3模型对象CSS3DObject
  var label = new CSS3DObject(div);
  div.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件
  // 设置HTML元素标签在three.js世界坐标中位置
  // label.position.set(x, y, z);
  //缩放CSS3DObject模型对象
  label.scale.set(0.2, 0.2, 0.2);//根据相机渲染范围控制HTML 3D标签尺寸
  label.rotateY(Math.PI / 2);//控制HTML标签CSS3对象姿态角度
  // label.rotateX(-Math.PI/2);
  return label;//返回CSS3模型标签    
}

// 创建一个HTML标签
function tag3DSprite(name) {
    
    
  // 创建div元素(作为标签)
  var div = document.createElement('div');
  div.innerHTML = name;
  div.classList.add('tag');
  //div元素包装为CSS3模型对象CSS3DSprite
  var label = new CSS3DSprite(div);
  div.style.pointerEvents = 'none';//避免HTML标签遮挡三维场景的鼠标事件
  // 设置HTML元素标签在three.js世界坐标中位置
  // label.position.set(x, y, z);
  //缩放CSS3DSprite模型对象
  label.scale.set(0.2, 0.2, 0.2);//根据相机渲染范围控制HTML 3D标签尺寸
  label.rotateY(Math.PI / 2);//控制HTML标签CSS3对象姿态角度
  // label.rotateX(-Math.PI/2);
  return label;//返回CSS3模型标签    
}

// 创建一个CSS2渲染器CSS2DRenderer
function labelRenderer(container) {
    
    
  var labelRenderer = new CSS3DRenderer();
  labelRenderer.setSize(container.offsetWidth, container.offsetHeight);
  labelRenderer.domElement.style.position = 'absolute';
  // 相对标签原位置位置偏移大小
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.left = '0px';
  // //设置.pointerEvents=none,以免模型标签HTML元素遮挡鼠标选择场景模型
  labelRenderer.domElement.style.pointerEvents = 'none';
  container.appendChild(labelRenderer.domElement);
  return labelRenderer;
}

export {
    
     tag3D, tag3DSprite, labelRenderer }

Box.ts [Create model + label]

import * as THREE from "three"
import initRenderer from "./core/renderer";
import {
    
     model } from "./core/model";
import initScene from "./core/scene";
import {
    
     labelRenderer as labelRenderer2D, tag as tag2D } from "./core/tag2D";
import {
    
     labelRenderer as labelRenderer3D, tag3D, tag3DSprite } from "./core/tag3D";

class Box {
    
    
    private scene;
    private camera;
    private renderer;
    private container;

    constructor(container) {
    
    
        this.container = container;
        this.scene = new THREE.Scene();
        this.init();
    }
    init() {
    
    
        // 初始化渲染器和相机
        let {
    
     renderer, camera, render } = initRenderer({
    
     scene: this.scene, container: this.container, labelRenderer2D: labelRenderer2D(this.container), labelRenderer3D: labelRenderer3D(this.container) });
        this.renderer = renderer;
        this.camera = camera;
        this.renderer.setClearColor("black");

        // 初始化场景
        initScene({
    
     scene: this.scene, container: this.container, renderer: this.renderer, camera: this.camera });

        //初始化模型
        this.initObjects();

        // 开始渲染
        render();
    }

    //绘制
    initObjects() {
    
    
        const box = new THREE.BoxGeometry(30, 30, 30);
        const material = new THREE.MeshLambertMaterial({
    
    
            color: 0x0000ff
        })
        // --------------------模型1
        const mesh1 = new THREE.Mesh(box, material);
        mesh1.position.z = 30;
        mesh1.position.x = 30;
        box.translate(0, 15, 0)
        this.scene.add(mesh1);

        // 添加CSS 2DObject标签
        var label2D = tag2D("CSS 2DObject 标签");//设置标签名称
        var pos1 = new THREE.Vector3();
        mesh1.getWorldPosition(pos1);//获取obj世界坐标、
        pos1.y += 30;
        label2D.position.copy(pos1);//标签标注在obj世界坐标
        this.scene.add(label2D);//标签插入场景 

        // --------------------模型2
        const mesh2 = mesh1.clone();
        mesh2.position.x = 100;
        this.scene.add(mesh2);

        // 添加CSS 3DObject标签
        var label3D = tag3D("CSS 3DObject 标签");//设置标签名称
        var pos2 = new THREE.Vector3();
        mesh2.getWorldPosition(pos2);//获取obj世界坐标、
        pos2.y += 30;
        label3D.position.copy(pos2);//标签标注在obj世界坐标
        this.scene.add(label3D);//标签插入场景 

        // --------------------模型3
        const mesh3 = mesh1.clone();
        mesh3.position.z = 100;
        this.scene.add(mesh3);

        // 添加CSS 3DSprite标签
        var label3DSprite = tag3DSprite("CSS 3DSprite 标签");//设置标签名称
        var pos3 = new THREE.Vector3();
        mesh3.getWorldPosition(pos3);//获取obj世界坐标、
        pos3.y += 30;
        label3DSprite.position.copy(pos3);//标签标注在obj世界坐标
        this.scene.add(label3DSprite);//标签插入场景 
    }
}
export default Box;

render.ts【Set up the renderer】

import * as THREE from "three";
import createCamera from "./camera";

const initRenderer = function (context) {
    
    
    let {
    
     scene, labelRenderer2D, labelRenderer3D } = context;
    let {
    
     camera, renderer } = createCamera(context);

    // 渲染
    const render = () => {
    
    
        renderer.render(scene, camera);
        labelRenderer2D.render(scene, camera); //渲染HTML标签对象 CSS2DObject 标签
        labelRenderer3D.render(scene, camera); //渲染HTML标签对象 CSS3DObject 标签

        //监听鼠标、键盘事件
        requestAnimationFrame(render);
    }
    return {
    
     camera, renderer, render };
}

export default initRenderer;

4. Source code

Go to the tag demo source code

おすすめ

転載: blog.csdn.net/bobo789456123/article/details/129464847