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

如何在基于Three.js R71的Forge Viewer中添加TextGeometry?

在Forge Viewer中使用Three.js生成自动文本的可行方案与踩坑解决

完全可以在Forge Viewer中实现自动生成文本的需求,不过因为Viewer内置的是Three.js R71这个旧版本,确实需要适配它的API和资源要求,我帮你梳理几个可行的方案,以及你遇到的问题的解决办法:

方案一:直接使用Three.js R71的TextGeometry

这是最贴合3D文本需求的方案,核心要解决字体加载的兼容性问题:

1. 准备对应版本的字体文件

R71的TextGeometry依赖的字体JSON格式和新版Three.js不兼容,你必须使用R71官方提供的字体文件(比如helvetiker_regular.typeface.json),可以从Three.js R71源码包的examples/fonts目录里获取,把它放到你的项目静态资源目录中。

2. 正确加载字体并创建文本

R71的字体加载和文本创建写法和新版有差异,参考下面的代码:

// 假设你已经初始化好了Viewer实例,这里用NOP_VIEWER指代
const viewer = NOP_VIEWER;

// 加载R71版本的字体
const fontLoader = new THREE.FontLoader();
fontLoader.load('/path/to/helvetiker_regular.typeface.json', (font) => {
  // 创建TextGeometry
  const textGeo = new THREE.TextGeometry('自动生成的文本', {
    font: font,
    size: 8,
    height: 1.5,
    curveSegments: 12, // 控制文本平滑度
    bevelEnabled: false
  });

  // 让文本居中(可选)
  textGeo.computeBoundingBox();
  const centerX = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
  textGeo.translate(centerX, 0, 0);

  // 创建材质与网格
  const textMat = new THREE.MeshPhongMaterial({ color: 0xff5500 });
  const textMesh = new THREE.Mesh(textGeo, textMat);

  // 设置文本位置(这里示例放在场景原点上方)
  textMesh.position.set(0, 15, 0);

  // 添加到Viewer场景并刷新渲染
  viewer.impl.scene.add(textMesh);
  viewer.impl.invalidate(true);
});

你遇到的「字体不存在」错误的原因

  • 大概率是用了新版Three.js的字体文件,格式不兼容;
  • 字体文件路径错误,要确保资源能被正确访问(本地测试要开服务器,避免跨域问题)。

方案二:Canvas转纹理的3D文本(更省心的替代方案)

如果不想纠结旧版本字体的问题,可以先在Canvas上绘制2D文本,再转换成Three.js纹理贴在平面上,兼容性更好:

const viewer = NOP_VIEWER;

// 创建Canvas并绘制文本
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 80;
ctx.fillStyle = '#ffffff';
ctx.font = '50px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('自动生成文本', canvas.width / 2, canvas.height / 2 + 15);

// 转成Three.js纹理
const texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

// 创建带纹理的平面
const planeGeo = new THREE.PlaneGeometry(20, 5);
const planeMat = new THREE.MeshBasicMaterial({ map: texture, transparent: true });
const textPlane = new THREE.Mesh(planeGeo, planeMat);

// 设置位置并添加到场景
textPlane.position.set(0, 10, 0);
viewer.impl.scene.add(textPlane);
viewer.impl.invalidate(true);

解决上层叠加Canvas的布局问题

如果你坚持用Viewer上层的独立Canvas,需要解决坐标映射和尺寸同步的问题:

  1. 同步Canvas尺寸:监听Viewer的窗口 resize 事件,让Canvas大小和Viewer容器一致:
const overlayCanvas = document.getElementById('text-overlay');
function syncCanvasSize() {
  overlayCanvas.width = viewer.container.clientWidth;
  overlayCanvas.height = viewer.container.clientHeight;
}
// 初始化和窗口变化时同步
syncCanvasSize();
viewer.addEventListener(Autodesk.Viewing.VIEWER_RESIZED_EVENT, syncCanvasSize);
  1. 正确映射3D坐标到2D:用Viewer的worldToClient方法把模型中的3D点转换成屏幕坐标,再定位Canvas上的文本:
// 示例:获取模型中某个3D点的屏幕位置
const worldPoint = new THREE.Vector3(10, 5, 0);
const screenPoint = viewer.worldToClient(worldPoint);

// 在Canvas上绘制文本到对应位置
const ctx = overlayCanvas.getContext('2d');
ctx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
ctx.fillStyle = '#ff0000';
ctx.font = '24px sans-serif';
ctx.fillText('标记文本', screenPoint.x, screenPoint.y);

以上几种方案都能实现「JavaScript自动生成文本,无需用户操作」的需求,你可以根据自己的场景选择最合适的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:16