You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js中点击生成的3D模态框添加文本失败求助

在Three.js的3D模态框中添加文本的解决方案

嘿,我看你已经搞定点击创建/移除3D模态框的逻辑了,但卡在给这个模态框加文本这一步对吧?其实Three.js里没法直接给Mesh塞文本,得用专门的方式来实现,我给你两种常用的解决方案,你可以根据需求选:

方法1:用TextGeometry创建3D文本(带立体效果)

这种方法能做出有厚度的3D文本,但需要提前加载字体文件(你可以从Three.js官方示例的fonts文件夹里拿,比如helvetiker_regular.typeface.json)。

修改你的onClick函数如下:

function onClick(object) { 
  if (uiPlane !== undefined) { 
    scene.remove(uiPlane); 
    // 记得同时移除文本网格,避免内存残留
    if (t) {
      scene.remove(t);
      t = undefined;
    }
    uiPlane = undefined; 
  } else { 
    var geometry = new THREE.PlaneGeometry(6, 2, 1); 
    var material = new THREE.MeshBasicMaterial( { color: new THREE.Color("rgb(242, 242, 242)"), side: THREE.DoubleSide }); 
    uiPlane = new THREE.Mesh(geometry, material); 
    uiPlane.name = 'dialog_' + object.name;
    // 把模态框放在目标物体上方,避免遮挡
    uiPlane.position.copy(object.position);
    uiPlane.position.y += 2;

    // --- 添加3D文本部分 ---
    // 建议提前全局加载字体,不要每次点击都加载,这里为了演示写在函数里
    const fontLoader = new THREE.FontLoader();
    fontLoader.load('helvetiker_regular.typeface.json', function(font) {
      const textGeometry = new THREE.TextGeometry('这是你的模态框文本', {
        font: font,
        size: 0.5, // 文本大小
        height: 0.1, // 文本厚度
        curveSegments: 12,
        bevelEnabled: true, // 边缘倒角
        bevelThickness: 0.03,
        bevelSize: 0.02
      });
      // 文本用黑色,和浅色模态框形成对比
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
      t = new THREE.Mesh(textGeometry, textMaterial);
      // 让文本居中
      textGeometry.center();
      t.position.copy(uiPlane.position);
      // 微调位置,让文本在模态框上方一点
      t.position.y += 0.2;
      scene.add(t);
    });

    scene.add(uiPlane); 
  }
}

注意:字体文件要放在正确的路径下,最好提前在页面加载时就加载好字体,不要每次点击都发起请求,影响性能。

方法2:用Canvas生成文本纹理(快速实现平面文本)

如果不需要3D立体效果,这种方法更简单,不需要额外字体文件,直接用浏览器支持的字体就能生成文本纹理:

function onClick(object) { 
  if (uiPlane !== undefined) { 
    scene.remove(uiPlane); 
    if (t) {
      scene.remove(t);
      t = undefined;
    }
    uiPlane = undefined; 
  } else { 
    var geometry = new THREE.PlaneGeometry(6, 2, 1); 
    var material = new THREE.MeshBasicMaterial( { color: new THREE.Color("rgb(242, 242, 242)"), side: THREE.DoubleSide }); 
    uiPlane = new THREE.Mesh(geometry, material); 
    uiPlane.name = 'dialog_' + object.name;
    uiPlane.position.copy(object.position);
    uiPlane.position.y += 2;

    // --- 用Canvas创建平面文本 ---
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    // 画布尺寸和模态框比例一致(100:1)
    canvas.width = 600;
    canvas.height = 200;
    // 画布背景设为透明或者和模态框同色
    ctx.fillStyle = '#f2f2f2';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    // 设置文本样式
    ctx.fillStyle = '#000000';
    ctx.font = '48px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    // 绘制文本到画布中心
    ctx.fillText('这是你的模态框文本', canvas.width/2, canvas.height/2);

    // 把画布转成Three.js纹理
    const textTexture = new THREE.CanvasTexture(canvas);
    const textMaterial = new THREE.MeshBasicMaterial({ 
      map: textTexture, 
      side: THREE.DoubleSide, 
      transparent: true 
    });
    // 创建文本平面,尺寸和模态框一致
    const textGeometry = new THREE.PlaneGeometry(6, 2);
    t = new THREE.Mesh(textGeometry, textMaterial);
    t.position.copy(uiPlane.position);
    // 让文本稍微靠前一点,避免和模态框重叠
    t.position.z += 0.1;
    scene.add(t);

    scene.add(uiPlane); 
  }
}

这种方法的好处是快速上手,不需要额外依赖,适合做简单的平面文本提示。

两种方法都能解决你的问题,选哪种看你要不要3D文本的效果~另外记得移除模态框时一定要把文本网格也一起移除,不然会堆积在场景里占用内存哦。

内容的提问来源于stack exchange,提问作者Lex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:26:34