Threejs进阶之五:使用CSS2DRenderer给模型添加HTML标签

本篇博客介绍了如何在Threejs中使用CSS2DRenderer为3D模型添加HTML标签,实现鼠标点击模型部位显示对应信息的效果。详细讲解了CSS2DRenderer的构造函数和方法,以及CSS2DObject对象的使用,包括如何创建HTML标签、设置标签位置、解决标签遮挡画布问题,并实现鼠标选中模型弹出标签的交互功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这一节给场景中的模型添加标签,想实现的效果是,通过鼠标点击场景中摩托车的某个部位,则在场景中出现一个标签,并在标签上显示该部位的信息。最终的效果图如下:
在这里插入图片描述
要实现上面的效果,需要用到CSS 2D渲染器,先来了解下CSS 2D渲染器

CSS2DRenderer(CSS 2D渲染器)

CSS2DRenderer(CSS 2D渲染器)可以把HTML元素作为标签标注到三维场景中,CSS2DRenderer是CSS3DRenderer(CSS 3D渲染器)的简化版本,它唯一支持的变换是位移。通过CSS2DRenderer我们可以将三维物体和基于HTML的标签相结合,来更好的表达场景中物体的信息。

构造函数

CSS2DRenderer()

方法

.getSize () 返回一个包含有渲染器宽和高的对象。

.render ( scene : Scene, camera : Camera ) 使用camera渲染scene。

.setSize (width : Number, height : Number) 将渲染器的尺寸调整为(width, height).

使用CSS2DRenderer

CSS2DRenderer是threejs提供的扩展库,在threejs文件包目录examples/jsm/renderers/,文件夹下面可以找到CSS2DRenderer.js扩展库。

CSS2DRenderer.js提供了两个类CSS2DRenderer(CSS2D渲染器)和CSS2DObject(CSS2D模型对象)

要使用CSS2DRenderer,我们需要先将其引入

// 引入CSS2渲染器CSS2DRenderer和CSS2模型对象CSS2DObject
import {
    CSS2DRenderer,CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'

创建HTML标签

在vue文件的模板中添加如下代码,都是基础的HTML语音,这里不再细说

<div id="label">
    <div style="position: relative; width: 139px; height: 167px;color: #ffffff;">
      <img src="../assets/images/info.png" alt="" style="width: 100%; position: absolute;left: 0px;top: 0px;"> 
      <div style="position: absolute; left: 48px;top: 4px;font-size: 12px;">
        <div style="font-size: 14px;font-weight: 400;">
          <span id="txtName">车身</span>
        </div>
        <div style="margin-top: 8px;margin-left: -25px;">
            <span style="color: #fff;font-weight: 300;">材质:</span>
            <span style="font-weight: 400;margin-left: 10px;" id="txtMaterial">金属</span>
        </div>
        <div style="margin-top: 8px;margin-left: -25px;">
            <span style="color: #fff;font-weight: 300;">颜色:</span>
            <span style="font-weight: 400;margin-left: 2px;" id="txtColor">红色</span>
        </div>
      </div>
    </div>
  </div>

添加上述代码后,我们创建的标签出现在了浏览器页面的左下方,这是典型的浏览器div的排列属性,但是这不是我们想要的,我们想要将这个div标签放到三维场景中去展示。这就涉及到了世界坐标xyz与屏幕坐标的转换,这是一个很麻烦的事情。好在threejs的扩展库CSS2DRenderer.js已经帮我们考虑到了这一点,给我们提供了CSS2DObject 对象
在这里插入图片描述

CSS2DObject 对象

通过CSS2DObject对象,可以把HTML元素转化为一个类似threejs网格模型的对象,即把CSS2DObject当成threejs的一个模型一样去设置位置.position或添加到场景中;

const div = document.querySelector('#label')
const tag 
<think>好的,用户现在想了解如何使用THREE.Mesh进行3D物体的姿态旋转。我需要结合他们提供的引用内容,特别是引用[1]、[2]、[3]、[4]中的相关代码,来构建一个示例。首先,我需要回忆Three.js中关于Mesh旋转的基本方法,比如使用rotation属性或者四元数quaternion。用户提供的引用[1]中有加载GLTF模型并播放动画的代码,其中涉及到了AnimationMixer,这可能和动画控制有关,但用户的问题是关于手动旋转Mesh的姿态,所以可能需要更基础的旋转方法。引用[2]是关于CSS2DRenderer的使用,可能不太相关,但需要确认。引用[3]提到了ShaderMaterial和自定义着色器,这可能涉及更高级的旋转控制,比如在着色器中处理旋转,但用户的问题可能更倾向于直接操作Mesh的旋转属性。引用[4]是关于材质的emissive属性设置,可能和旋转无关。接下来,我需要确定用户的需求是基础旋转操作,比如绕X、Y、Z轴旋转,或者使用四元数进行更复杂的姿态调整。通常,Three.js中的Mesh对象有rotation属性,包含x、y、z三个轴的旋转角度(弧度制),以及一个四元数属性quaternion。需要注意的是,直接设置rotation和quaternion会有冲突,因为四元数会覆盖rotation的值,所以需要决定使用哪种方式。在示例代码中,应该展示如何通过修改rotation属性来旋转物体,比如mesh.rotation.x +=0.01。同时,可能需要提到使用四元数的方法,比如使用setFromAxisAngle来设置绕某个轴的旋转。此外,用户可能还需要了解在动画循环中更新旋转,如引用[1]中的animate函数,使用requestAnimationFrame来持续更新。另外,引用[3]中的着色器示例可能涉及到在顶点着色器中处理旋转,但这可能超出了用户当前的问题范围。不过,如果用户需要更高级的控制,可以提及自定义着色器的可能性,但重点应放在基本的Mesh旋转上。 还需要注意Three.js中的旋转顺序,默认是'XYZ',但可以通过设置mesh.rotation.order来改变。这可能是一个进阶内容,但用户的问题可能只需要基础示例。最后,结合用户提供的引用,可能需要引用到加载模型的部分(引用[1]),比如在加载模型后对模型进行旋转操作。此外,确保代码示例包含创建场景、相机、渲染器,以及动画循环,这样用户可以直接运行示例。 总结回答结构:首先介绍Three.js中Mesh的旋转属性,然后给出基本旋转的代码示例,包括静态设置和动画循环中的动态旋转,接着介绍四元数的使用,最后提到旋转顺序和注意事项。引用相关的代码部分,如动画循环参考引用[1],材质设置参考引用[4]等。</think>### THREE.Mesh 三维物体姿态旋转实现指南 在 Three.js 中,通过 `THREE.Mesh` 的旋转属性可以实现三维物体的姿态控制。以下是关键方法和示例代码: --- #### **1. 基础旋转控制** 通过 `rotation` 属性实现欧拉角旋转,支持 XYZ 三轴独立控制: ```javascript // 创建立方体 const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); // 绕 Y 轴旋转 45 度(弧度制) cube.rotation.y = Math.PI / 4; // 动态旋转动画(参考引用[1]的动画循环) function animate() { requestAnimationFrame(animate); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); } animate(); ``` --- #### **2. 四元数姿态控制** 使用四元数(quaternion)实现复杂空间旋转,避免万向节死锁: ```javascript // 绕任意轴旋转(如绕对角线轴旋转30度) const axis = new THREE.Vector3(1, 1, 0).normalize(); const angle = Math.PI / 6; // 30度 cube.quaternion.setFromAxisAngle(axis, angle); // 结合动画更新 function updateRotation() { cube.quaternion.multiply( new THREE.Quaternion().setFromAxisAngle(axis, 0.02) ); } ``` --- #### **3. 组合旋转与层级控制** 通过 `Object3D` 层级结构实现复合旋转: ```javascript // 创建父子对象 const parent = new THREE.Object3D(); const child = new THREE.Mesh(geometry, material); parent.add(child); // 父对象绕Y轴旋转,子对象绕自身X轴旋转 parent.rotation.y = Math.PI/3; child.rotation.x = Math.PI/4; ``` --- #### **4. 着色器控制旋转(高级)** 在自定义着色器中实现旋转(参考引用[3]的着色器示例): ```glsl // 顶点着色器 uniform float uRotationAngle; void main() { mat4 rotationMat = rotationMatrix(normalize(vec3(1,1,0)), uRotationAngle); gl_Position = projectionMatrix * modelViewMatrix * rotationMat * vec4(position, 1.0); } ``` 通过 `ShaderMaterial` 动态传递旋转参数[^3]: ```javascript const shaderMaterial = new THREE.ShaderMaterial({ uniforms: { uRotationAngle: { value: 0 } }, vertexShader: vertexShaderCode, fragmentShader: fragmentShaderCode }); // 更新旋转角度 function animate() { shaderMaterial.uniforms.uRotationAngle.value += 0.01; } ``` --- #### **5. 关键注意事项** - **旋转顺序**:通过 `mesh.rotation.order` 设置旋转顺序(默认 `XYZ`) - **性能优化**:复杂旋转建议使用四元数,避免连续修改欧拉角 - **矩阵更新**:手动修改属性后需调用 `mesh.updateMatrix()` - **光照同步**:旋转后需更新法线向量(调用 `mesh.normalMatrixNeedsUpdate = true`) --- ```javascript // 完整示例(包含模型加载参考引用[1]) const loader = new GLTFLoader(); loader.load('robot.gltf', (gltf) => { const model = gltf.scene; model.rotation.set(0, Math.PI/2, 0); // 初始姿态设置 scene.add(model); // 持续绕Y轴旋转 function animate() { model.rotation.y += 0.01; renderer.render(scene, camera); requestAnimationFrame(animate); } animate(); }); ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九仞山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值