如何在Three.js中添加2D文本标签?已尝试Sprites、FontLoader等
在Three.js中为3D物体添加2D文本标签的实现指引
问题描述
我想在3D物体旁添加如图所示的2D文本标签,试过Sprites(新版Three.js里似乎无法使用)、FontLoader及多种渲染机制都没成功。了解到可以用CSS3D,但不清楚该从示例代码中借鉴哪些内容,附上我的关键代码片段,希望能得到方向指引。
我的关键代码
<script src="https://unpkg.com/three@0.132.2/build/three.min.js"></script> <script src="https://unpkg.com/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script> <script src="https://unpkg.com/three@0.132.2/examples/js/loaders/DRACOLoader.js"></script> <script src="https://unpkg.com/three@0.132.2/examples/js/controls/OrbitControls.js"></script> <canvas id="c"></canvas> <script> window.addEventListener('load', init); function init() { const width = window.innerWidth; const height = window.innerHeight; const canvasElement = document.querySelector('#c'); const renderer = new THREE.WebGLRenderer({ canvas: canvasElement, }); renderer.setSize(width, height); const scene = new THREE.Scene(); scene.background = new THREE.Color( 0xf5e8c6 ); // 补充loader初始化(原代码遗漏部分) const loader = new THREE.GLTFLoader(); const dracoLoader = new THREE.DRACOLoader(); dracoLoader.setDecoderPath('js/draco/'); // 若使用DRACO压缩需设置解码器路径 loader.setDRACOLoader(dracoLoader); loader.load('js/PricklyPearObject/scene.gltf', (gltf) => { const model = gltf.scene; model.scale.set( 0.1,0.1,0.1); model.position.set(-2, 0, 0); scene.add(model); }); } </script>
基于CSS3D的实现步骤与修改代码
1. 引入CSS3D相关依赖
在现有脚本后添加CSS3DRenderer的引用:
<script src="https://unpkg.com/three@0.132.2/examples/js/renderers/CSS3DRenderer.js"></script>
2. 完善初始化逻辑(相机、控制器、CSS渲染器)
修改init函数,补充核心功能代码:
function init() { const width = window.innerWidth; const height = window.innerHeight; const canvasElement = document.querySelector('#c'); const renderer = new THREE.WebGLRenderer({ canvas: canvasElement, }); renderer.setSize(width, height); // 创建相机 const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100); camera.position.set(0, 0, 5); // 创建轨道控制器 const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; // 创建CSS3D渲染器 const cssRenderer = new THREE.CSS3DRenderer(); cssRenderer.setSize(width, height); cssRenderer.domElement.style.position = 'absolute'; cssRenderer.domElement.style.top = '0'; cssRenderer.domElement.style.pointerEvents = 'none'; // 不遮挡WebGL画布交互 document.body.appendChild(cssRenderer.domElement); const scene = new THREE.Scene(); scene.background = new THREE.Color( 0xf5e8c6 ); const loader = new THREE.GLTFLoader(); const dracoLoader = new THREE.DRACOLoader(); dracoLoader.setDecoderPath('js/draco/'); loader.setDRACOLoader(dracoLoader); loader.load('js/PricklyPearObject/scene.gltf', (gltf) => { const model = gltf.scene; model.scale.set( 0.1,0.1,0.1); model.position.set(-2, 0, 0); scene.add(model); // 创建并添加文本标签 const labelDiv = document.createElement('div'); labelDiv.style.padding = '4px 8px'; labelDiv.style.background = 'rgba(255,255,255,0.9)'; labelDiv.style.borderRadius = '4px'; labelDiv.style.fontSize = '14px'; labelDiv.style.whiteSpace = 'nowrap'; labelDiv.textContent = '仙人掌'; // 将HTML元素包装为CSS3DObject const labelObject = new THREE.CSS3DObject(labelDiv); // 定位到模型上方偏右位置(数值根据模型缩放调整) labelObject.position.copy(model.position); labelObject.position.y += 1; labelObject.position.x += 0.5; // 让标签始终面向相机 labelObject.lookAt(camera.position); scene.add(labelObject); }); // 渲染循环:同时渲染WebGL和CSS3D场景 function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); cssRenderer.render(scene, camera); // 如需标签持续跟随相机视角,可在此处更新朝向 // const label = scene.getObjectByName('自定义标签名称'); // if(label) label.lookAt(camera.position); } animate(); }
核心要点说明
- CSS3D的本质是将HTML元素转换为Three.js可识别的对象,能和3D模型一起参与场景的位置、旋转变换
- CSS3DRenderer的DOM元素必须设置绝对定位,叠加在WebGL画布之上,关闭
pointerEvents避免遮挡画布交互 - 标签位置需根据模型实际缩放比例调整,确保显示在模型旁合适位置
- 若需标签始终跟随相机视角,可在渲染循环中调用
labelObject.lookAt(camera.position)更新朝向
内容的提问来源于stack exchange,提问作者Ro Ba
相关产品推荐
相关产品推荐

