You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Three.js场景上方添加2D文本图层?

在Three.js 3D场景上方添加2D文本图层的几种方法

嘿,要在你的Three.js 3D场景上加2D文本图层其实很简单,我给你分享两种最常用的实现方式:


方法一:用普通HTML元素叠加(最简单)

这种方法不需要额外引入Three.js扩展,直接利用CSS绝对定位把HTML文本元素放在Three.js渲染的Canvas上方即可,适合快速实现静态文本需求。

修改后的完整代码:

<html>
<head>
    <title>First page.</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link href="/errordocs/style/general.css" rel="stylesheet" type="text/css">
    <script src="https://threejs.org/build/three.js" crossorigin="anonymous"></script>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; }
        /* 2D文本图层样式 */
        .text-overlay {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            font-size: 24px;
            z-index: 10; /* 确保在Canvas上方 */
            pointer-events: none; /* 可选:让鼠标事件穿透文本,不影响Three.js交互 */
        }
    </style>
</head>
<body>
    <!-- 2D文本元素 -->
    <div class="text-overlay">这是3D场景上方的2D文本</div>
    
    <script>
        var scene, camera, renderer;
        var geometry, material, mesh;

        init();
        animate();

        function init() {
            scene = new THREE.Scene();
            scene.background = new THREE.Color( 0x222222 );

            camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
            camera.position.z = 1;

            geometry = new THREE.SphereGeometry( 0.1, 20, 20 );
            material = new THREE.MeshNormalMaterial();
            mesh = new THREE.Mesh( geometry, material );
            scene.add( mesh );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );
        }

        // 添加动画循环让球体动起来(可选)
        function animate() {
            requestAnimationFrame( animate );
            mesh.rotation.x += 0.01;
            mesh.rotation.y += 0.02;
            renderer.render( scene, camera );
        }
    </script>
</body>
</html>

关键点说明:

  • 给Canvas设置position: absolute,让文本元素可以正确叠加在其上方
  • 文本元素的z-index要大于Canvas(默认Canvas无z-index,设置10足够保证层级)
  • pointer-events: none是可选设置,如果你的3D场景需要鼠标交互,这个属性可以让鼠标点击穿透文本,直接作用到Three.js场景上

方法二:用Three.js的CSS2DRenderer(贴合Three.js生态)

如果你希望文本能和3D场景有更紧密的关联(比如后续要让文本跟着3D物体移动),可以用Three.js官方提供的CSS2DRenderer,它专门用来创建可关联3D空间的2D标签。

修改后的完整代码:

<html>
<head>
    <title>First page.</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link href="/errordocs/style/general.css" rel="stylesheet" type="text/css">
    <!-- 引入CSS2DRenderer相关脚本 -->
    <script src="https://threejs.org/examples/js/renderers/CSS2DRenderer.js"></script>
    <script src="https://threejs.org/build/three.js" crossorigin="anonymous"></script>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
        /* 文本标签样式 */
        .label {
            color: white;
            font-size: 24px;
            padding: 8px;
            background: rgba(0,0,0,0.5);
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <script>
        var scene, camera, renderer, labelRenderer;
        var geometry, material, mesh;

        init();
        animate();

        function init() {
            scene = new THREE.Scene();
            scene.background = new THREE.Color( 0x222222 );

            camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
            camera.position.z = 1;

            // 创建球体
            geometry = new THREE.SphereGeometry( 0.1, 20, 20 );
            material = new THREE.MeshNormalMaterial();
            mesh = new THREE.Mesh( geometry, material );
            scene.add( mesh );

            // 创建WebGLRenderer
            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            // 创建CSS2DRenderer和文本标签
            labelRenderer = new THREE.CSS2DRenderer();
            labelRenderer.setSize( window.innerWidth, window.innerHeight );
            labelRenderer.domElement.style.position = 'absolute';
            labelRenderer.domElement.style.top = '0';
            document.body.appendChild( labelRenderer.domElement );

            // 创建文本元素
            var textElement = document.createElement('div');
            textElement.className = 'label';
            textElement.textContent = '这是CSS2DRenderer创建的2D文本';
            // 创建CSS2DObject并添加到场景
            var label = new THREE.CSS2DObject(textElement);
            // 设置标签位置(这里放在球体上方一点的位置)
            label.position.set(0, 0.2, 0);
            scene.add(label);
        }

        function animate() {
            requestAnimationFrame( animate );
            mesh.rotation.x += 0.01;
            mesh.rotation.y += 0.02;
            // 同时渲染WebGL场景和2D标签
            renderer.render( scene, camera );
            labelRenderer.render( scene, camera );
        }
    </script>
</body>
</html>

关键点说明:

  • 需要额外引入CSS2DRenderer.js脚本
  • CSS2DObject可以把普通HTML元素包装成Three.js的场景对象,支持设置3D空间位置
  • 动画循环里需要同时调用renderer.render()labelRenderer.render(),才能同时渲染3D场景和2D文本

两种方法都能实现你的需求:如果只是要固定在场景上方的静态文本,方法一足够简单;如果需要文本和3D元素有交互关联,方法二更合适。

内容的提问来源于stack exchange,提问作者dàhóngpāo

火山引擎 最新活动