Three.js 中如何给 3D 模型添加文字标签?

在做 3D 可视化项目时,我们经常需要给场景中的物体、房间、设备等加上文字说明,比如:

  • 房间号(101、102…)

  • 设备标签(空调、电梯、传感器)

  • 人员名字或状态

问题是:Three.js 本身不能直接显示文字。
我们需要一个办法,把文字“画”出来,再贴到 3D 世界里。

本文就带你实现:用 Canvas 生成文字 → 转换为纹理 → 在 Three.js 中作为标签展示


🔹 为什么不用 HTML 直接写?

Three.js 有两种常见方式做标签:

  1. HTML + CSS2DRenderer

    • 直接用 DOM 元素 (<div>) 作为标签,叠加在 3D 场景上

    • 优点:样式好写,和写网页差不多

    • 缺点:标签不是真正的 3D 对象,旋转时可能不跟随场景

  2. Canvas 生成纹理 → Sprite (本文讲的方式)

    • 用 Canvas 画一个文字框(可带背景、边框、圆角)

    • 转换为 Three.js 纹理 → 贴到 Sprite

    • 优点:标签是真正的 3D 元素,跟随相机缩放、旋转

    • 缺点:需要写点 Canvas 绘图代码

 所以,当你需要“标签和模型在同一个 3D 世界里”时,Canvas 方案更合适。

🔹 实现思路

  1. 在 Canvas 上画一个“圆角矩形 + 文本”的小图片

  2. 把 Canvas 转换为 THREE.CanvasTexture

  3. THREE.SpriteMaterial 包装成材质

  4. 创建 THREE.Sprite 并放到场景中

  5. 调整位置和缩放

🔹 代码实现

1. 创建一个文字标签

function createBoxLabel(text, options = {}) {
  const {
    color = "white",        // 文字颜色
    fontSize = 28,          // 字体大小
    bgColor = "black",      // 背景颜色
    borderColor = "white",  // 边框颜色
    borderWidth = 2,        // 边框宽度
    borderRadius = 8,       // 圆角半径
    padding = 10            // 内边距
  } = options;

  // 创建画布
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  canvas.width = 412;
  canvas.height = 156;

  // 绘制圆角矩形背景
  function roundRect(ctx, x, y, w, h, r) {
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + w - r, y);
    ctx.quadraticCurveTo(x + w, y, x + w, y + r);
    ctx.lineTo(x + w, y + h - r);
    ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
    ctx.lineTo(x + r, y + h);
    ctx.quadraticCurveTo(x, y + h, x, y + h - r);
    ctx.lineTo(x, y + r);
    ctx.quadraticCurveTo(x, y, x + r, y);
    ctx.closePath();
    ctx.fillStyle = bgColor;
    ctx.fill();
    ctx.lineWidth = borderWidth;
    ctx.strokeStyle = borderColor;
    ctx.stroke();
  }

  roundRect(context, 0, 0, canvas.width, canvas.height, borderRadius);

  // 写文字
  context.fillStyle = color;
  context.font = `${fontSize}px Arial`;
  context.textAlign = "center";
  context.textBaseline = "middle";
  context.fillText(text, canvas.width / 2, canvas.height / 2);

  // 转换为 Three.js 纹理
  const texture = new THREE.CanvasTexture(canvas);
  const material = new THREE.SpriteMaterial({ map: texture, transparent: true });
  const sprite = new THREE.Sprite(material);

  // 缩放到合适大小
  sprite.scale.set(1.5, 0.75, 1);

  return sprite;
}

2. 添加到场景

function addLabelAtPosition(text, x, y, z) {
  const label = createBoxLabel(text, {
    color: "white",
    bgColor: "black",
    borderColor: "#007bff"
  });
  label.position.set(x, y, z);
  scene.add(label);
  return label;
}

// 示例:在 3D 场景中某个位置加标签
addLabelAtPosition("101 房间", 0.1, 0.2, -3.2);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值