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

Three.js教程:如何在r.64+版本中定位文本精灵?

嘿,我来帮你搞定这个问题!Three.js r64+版本在Sprite的处理上确实有一些小变化,咱们一步步调整旧代码,实现Box边缘的边长标注。

适配r64+的文本精灵创建函数

首先更新旧版的makeTextSprite函数,适配新版本的API:

function makeTextSprite(message, opts) {
  const parameters = opts || {};
  const fontface = parameters.fontface || 'Arial';
  const fontsize = parameters.fontsize || 32;
  const textColor = parameters.textColor || '#ffffff';
  const bgColor = parameters.bgColor || 'rgba(0,0,0,0.5)';

  // 创建画布并设置上下文
  const canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');
  
  // 先设置字体,计算文本尺寸
  context.font = `${fontsize}px ${fontface}`;
  const metrics = context.measureText(message);
  const textWidth = metrics.width;
  const textHeight = fontsize * 1.2; // 预留行高,避免文字被截断

  // 调整画布尺寸,给文本加边距提升可读性
  canvas.width = textWidth + 20;
  canvas.height = textHeight + 10;
  // 画布尺寸变更后重新获取上下文
  context = canvas.getContext('2d');
  context.font = `${fontsize}px ${fontface}`;
  
  // 绘制半透明背景(可选,让文本在复杂场景中更清晰)
  context.fillStyle = bgColor;
  context.fillRect(0, 0, canvas.width, canvas.height);
  
  // 绘制文本,居中对齐
  context.fillStyle = textColor;
  context.textBaseline = 'middle';
  context.textAlign = 'center';
  context.fillText(message, canvas.width / 2, canvas.height / 2);

  // 创建纹理并标记需要更新
  const texture = new THREE.Texture(canvas);
  texture.needsUpdate = true; // 这一步很关键,否则纹理不会生效

  // 创建精灵材质
  const spriteMaterial = new THREE.SpriteMaterial({
    map: texture,
    transparent: true,
    depthTest: false, // 可选:关闭深度测试,让文本始终显示在最上层
  });

  // 创建精灵并调整缩放
  const sprite = new THREE.Sprite(spriteMaterial);
  const scaleFactor = 0.1; // 根据场景整体缩放调整这个值
  sprite.scale.set(textWidth * scaleFactor, textHeight * scaleFactor, 1);
  
  return sprite;
}
定位文本精灵到Box边缘中点

接下来的核心是计算Box每个边缘的中点坐标,把精灵放在对应位置。假设你已经创建了Box网格:

// 创建示例Box(尺寸:x=2,y=1,z=3)
const boxGeometry = new THREE.BoxGeometry(2, 1, 3);
const boxMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
scene.add(boxMesh);

手动定位关键边缘

你可以手动计算边缘中点,比如:

// 标注x方向边长(正面底部边缘,中点(0, -0.5, 1.5))
const xLengthSprite = makeTextSprite('2', { fontsize: 24, textColor: '#ff0000' });
xLengthSprite.position.set(0, -0.5, 1.51); // z轴微移,避免和Box表面重合
scene.add(xLengthSprite);

// 标注y方向边长(右侧垂直边缘,中点(1, 0, 1.5))
const yLengthSprite = makeTextSprite('1', { fontsize: 24, textColor: '#00ff00' });
yLengthSprite.position.set(1.01, 0, 1.5); // x轴微移
scene.add(yLengthSprite);

// 标注z方向边长(顶部深度边缘,中点(1, 0.5, 0))
const zLengthSprite = makeTextSprite('3', { fontsize: 24, textColor: '#0000ff' });
zLengthSprite.position.set(1, 0.51, 0); // y轴微移
scene.add(zLengthSprite);

自动遍历所有边缘标注

如果要给Box的所有边缘自动标注,可以利用computeEdges()方法获取所有边缘,批量计算中点:

// 先计算Box的所有边缘
boxGeometry.computeEdges();

// 遍历每个边缘,创建文本精灵
boxGeometry.edges.forEach(edge => {
  // 获取边缘的两个顶点
  const v1 = boxGeometry.vertices[edge[0]];
  const v2 = boxGeometry.vertices[edge[1]];
  
  // 计算边缘中点坐标
  const midPoint = new THREE.Vector3(
    (v1.x + v2.x) / 2,
    (v1.y + v2.y) / 2,
    (v1.z + v2.z) / 2
  );
  
  // 计算边长并格式化
  const length = v1.distanceTo(v2).toFixed(1);
  
  // 创建文本精灵并定位
  const sprite = makeTextSprite(length, { fontsize: 20 });
  sprite.position.copy(midPoint);
  
  // 微移精灵,避免和Box线框重合
  const offset = midPoint.clone().normalize().multiplyScalar(0.05);
  sprite.position.add(offset);
  
  scene.add(sprite);
});
重要注意事项
  • 精灵缩放调整:scaleFactor的值需要根据你的场景整体缩放比例来调整,确保文本大小适配场景。
  • 遮挡问题:如果文本被Box遮挡,可以开启depthTest: false让精灵始终显示在最前面,或者微调position的偏移量。
  • 动态文本更新:如果需要修改精灵的文本内容,更新canvas后一定要设置texture.needsUpdate = true,否则纹理不会刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:09:42