本文介绍: ThreeJs渲染中创建的网格模型,有时候我们需要给模型添加标签文字,方便识别不同的物体。这时候我们可以使用这两个库,里面提供了三种打标签的方式,随着相机角度的变化,三种标签的显示效果各不相同。
一、概述
ThreeJs渲染中创建的网格模型,有时候我们需要给模型添加标签文字,方便识别不同的物体。
这时候我们可以使用CSS3DRenderer
、CSS2DRenderer
这两个库,里面提供了三种打标签的方式,随着相机角度的变化,三种标签的显示效果各不相同。
三种标签分别是: CSS 2DObject、CSS 3DObject 标签、CSS 3DSprite 标签
二、效果预览
1、角度不同
2、距离不同
3、区别简述
可以看到,CSS 2DObject
、CSS 3DSprite
都可以让标签永远正对当前相机视角。不同的是,CSS 2DObject
标签的尺寸不会受远近影响;CSS 3DSprite
标签的尺寸受远近影响,远小近大;
CSS 3DObject
标签朝向固定,不会随视角变化而改变,就仿佛是创建的模型对象,但实际这三种标签都是使用html+css
来实现的,并且CSS 3DObject
标签的大小也会受远近影响,远小近大。
三、代码实现
tag2D.js【创建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【创建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【创建模型+标签】
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【设置渲染器】
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;
四、源码
前往标签demo源码
原文地址:https://blog.csdn.net/bobo789456123/article/details/129464847
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_46366.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。