提示词

使用Three.js的SpriteMaterial和Canvas API创建3D场景中的城市名称标签,实现动态文本标签的随机分布和颜色变化效果。

效果拆解

效果 实现方式
城市数据加载 使用fetch API获取JSON格式的城市数据
Canvas文本渲染 创建Canvas元素并使用2D上下文绘制文本
纹理生成 将Canvas转换为DataURL并创建Three.js纹理
Sprite标签 使用SpriteMaterial和Sprite创建3D文本标签
随机分布 在3D空间中随机设置标签位置
颜色变化 为每个标签生成随机颜色

核心技术点

1. Canvas文本创建函数

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const createCanvasText = ({ dpr = 1 } = {}) => {
  return ({ text = '', color = '#ffffff' } = {}) => {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    
    canvas.width = 512 * dpr
    canvas.height = 128 * dpr
    
    ctx.fillStyle = color
    ctx.font = `${64 * dpr}px Arial`
    ctx.textAlign = 'center'
    ctx.textBaseline = 'middle'
    
    ctx.fillText(text, canvas.width / 2, canvas.height / 2)
    
    return canvas
  }
}

2. 随机颜色生成

JAVASCRIPT
1
const getColor = () => '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0')

3. 城市标签创建

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const citys = await fetch(FILE_HOST+'files/json/city.json').then(res => res.json())
const updateCanvasText = createCanvasText({ dpr: 1.4 })

for (const key in citys) {
  const canvas = updateCanvasText({ text: key, color: getColor() })
  const texture = new THREE.TextureLoader().load(canvas.toDataURL())
  const material = new THREE.SpriteMaterial({ map: texture })
  const sprite = new THREE.Sprite(material)
  sprite.scale.set(canvas.width / canvas.height, 1, 1)
  
  sprite.position.set(
    Math.random() * 20 - 10,
    Math.random() * 20 - 10,
    Math.random() * 20 - 10
  )
  
  scene.add(sprite)
}

调试技巧

  1. Canvas尺寸调整:通过dpr参数调整Canvas的清晰度
  2. 字体大小:根据Canvas尺寸调整字体大小以获得最佳显示效果
  3. 标签缩放:根据文本长度调整Sprite的scale属性
  4. 颜色对比度:确保文本颜色与背景有足够的对比度

扩展思路

  1. 交互效果:添加鼠标悬停高亮效果
  2. 动画效果:实现标签的浮动或旋转动画
  3. 数据可视化:根据城市数据改变标签大小或颜色
  4. 点击事件:添加点击标签显示详细信息的功能
  5. 性能优化:使用对象池管理大量标签
  6. 样式定制:支持自定义字体、边框、阴影等样式