【Three.js】使用精灵图Sprite创建面朝相机的文本标注

目录

🐝前言

🐝canvas创建文字

🐝将canvas作为纹理贴图加载到sprite中 

🐝封装方法


🐝前言

在Three.js中精灵Sprite是一个总是面朝摄像机的平面,它通常和纹理贴图结合使用,贴图可以是一张图片,也可以是我们使用canvas绘制出来的任何东西。所以我们可以先使用canvas绘制文字,然后将它作为纹理贴图贴到精灵平面上,就可以创建面朝相机的文本标注了。

🐝canvas创建文字

// 创建canvas标签
const canvas = document.createElement('canvas')
// 获取canvas上下文对象
const context = canvas.getContext('2d')
// 设置画布大小
canvas.width = 150
canvas.height = 100
// 设置画布背景颜色
context.fillStyle = '#f0f0f0'
context.fillRect(0, 0, canvas.width, canvas.height)
// 绘制文字
context.font = '28px 宋体'
context.fillStyle = '#ff0000'
context.fillText('测试文字', 10, canvas.height / 2)
// 添加到页面上
document.body.appendChild(canvas)

context.fillText(text, x, y, maxWidth) : 用于在画布上绘制文字,它的四个参数分别是:

text:需要绘制的文本

x:开始绘制文本的x坐标

y:开始绘制文本的y坐标

maxWidth:(可选)允许的最大文本长度

 

🐝将canvas作为纹理贴图加载到sprite中 

 将canvas创建为threejs纹理对象

const texture = new THREE.Texture(canvas)
texture.needsUpdate = true // 触发纹理更新

创建Sprite对象并添加贴图材质

const material = new THREE.SpriteMaterial({
  map: texture,
  color: '#f0f0f0'
})
const sprite = new THREE.Sprite(material)

设置精灵对象大小、位置和旋转

👉注意:我们无法直接对精灵平面做旋转操作,但是可以通过对材质做旋转来实现相同的效果。

sprite.scale.set(2, 1, 1)
sprite.position.set(1, 0, 0)
sprite.material.rotation = Math.PI / 4
scene.add(sprite)

🐝封装方法

const createSpriteTextLabel = (data) => {
  const {text, position, direction, size, color} = {...data}
  const canvas = document.createElement('canvas')
  const context = canvas.getContext('2d')

  const fontSize = 36
  const font = `${fontSize}px Arial`
  const padding = 10
  const textWidth = context.measureText(text).width

  canvas.width = textWidth * 3.5 + padding * 2
  canvas.height = fontSize * 2 + padding * 2

  context.font = font
  context.fillStyle = color
  context.fillText(text, padding, canvas.height / 1.6)

  const texture = new THREE.Texture(canvas)
  texture.needsUpdate = true

  // 获取贴图的宽度和高度
  const textureWidth = canvas.width
  const textureHeight = canvas.height

  const material = new THREE.SpriteMaterial({
    map: texture,
    transparent: true,
  })
  const sprite = new THREE.Sprite(material)

  // 根据贴图的宽高比调整精灵的比例,保持贴图不变形
  const aspectRatio = textureWidth / textureHeight
  sprite.scale.set(size * aspectRatio, size, 1)
  sprite.position.copy(position)

  // 计算精灵的旋转角度
  sprite.material.rotation = Math.atan2(direction.y, direction.x)

  return sprite
}

// 使用
const spriteText = createSpriteTextLabel({
  text: '测试文字', 
  position: new THREE.Vector3(1, 0, 0),   // 文本位置
  direction: new THREE.Vector3(1, 1, 0),  // 文本方向
  size: 1,                                // 文本大小
  color: '#00ff00'                        // 文本颜色
})
scene.add(spriteText)

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-20 15:36:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-20 15:36:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-20 15:36:03       82 阅读
  4. Python语言-面向对象

    2024-03-20 15:36:03       91 阅读

热门阅读

  1. 解释关系型数据库和非关系型数据库的区别

    2024-03-20 15:36:03       49 阅读
  2. C 宏定义LOG日志输出案例

    2024-03-20 15:36:03       38 阅读
  3. C 作用域规则

    2024-03-20 15:36:03       43 阅读
  4. C 语言string.h常见函数用法

    2024-03-20 15:36:03       43 阅读
  5. vue2 实战:作用域插槽

    2024-03-20 15:36:03       43 阅读
  6. Linux -- 常用命令积累

    2024-03-20 15:36:03       43 阅读
  7. 【Cesium】根据相机距离隐藏或显示模型

    2024-03-20 15:36:03       42 阅读
  8. Vue2 和Vue3 双向数据绑定的区别和原理

    2024-03-20 15:36:03       42 阅读
  9. Leetcode-03-无重复字符的最长子串

    2024-03-20 15:36:03       43 阅读
  10. 我的自建博客之旅03之vuepress和Vitepress

    2024-03-20 15:36:03       42 阅读