美文网首页
three.js - 3D Text

three.js - 3D Text

作者: 闪电西兰花 | 来源:发表于2024-01-21 15:50 被阅读0次
image.png
  • 最终效果如上图所示,实现一个3D Text,使用了MeshMatcapMaterialFontLoaderTorusGeometry
  • 首先创建一个带有坐标系的基础场景
  // 导入three.js
  import * as THREE from 'three'
  // 导入轨道控制器
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

  /**
   * scene
  **/
  const scene = new THREE.Scene()

  /**
   * camera
  **/
  const camera = new THREE.PerspectiveCamera(
    45, 
    window.innerWidth / window.innerHeight, 
    0.1, 
    1000
  )
  camera.position.set(0, 0, 10)
  camera.lookAt(0, 0, 0)

  /**
   * renderer
  **/
  const renderer = new THREE.WebGLRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  document.body.appendChild(renderer.domElement)

  /**
   * axesHelper
  **/
  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)

  /**
   * controls
  **/
  const controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true

  /**
   * render
  **/
  function animate () {
    controls.update()
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
  }
  animate()
  • 导入 FontLoaderTextGeometryFontLoader是一个用于加载JSON格式字体的类,TextGeometry是一个将文本生成单一几何体的类,他们都是附件组件,必须显示导入
  // 导入FontLoader
  import { FontLoader } from 'three/addons/loaders/FontLoader.js';
  // 导入TextGeometry
  import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
  • 导入成功后,准备一个字体文件,我们这里用的是three.js自带的,将nodel_modules文件夹下'three/examples/fonts/'该路径下的helvetiker_regular.typeface.jsonLICENSE文件提取出来,放在我们项目的public路径下,一个通常用于存放静态文件的地方
    image.png
  • 使用FontLoader加载字体,并用TextGeometry生成几何体
    • 这里建议先使用MeshBasicMaterial,设置wireframe: true便于观察字体的相关属性,例如bevelThicknessbevelSizebevelSegments
    • 这一步完成后的效果如下图
  /*
    * font
  */
  const fontLoader = new FontLoader() 
  fontLoader.load('../public/font/helvetiker_regular.typeface.json', (font) => {
    const textGeometry = new TextGeometry('Hello Three.js', {
      font, // font实例
      size: 0.5, // 字体大小
      height: 0.2, // 文本厚度
      curveSegments: 6, // 曲线上点的数量
      bevelEnabled: true, // 开启斜角
      bevelThickness: 0.03, // 上斜角深度
      bevelSize: 0.02, // 斜角与原始文本之间的延伸距离
      bevelOffset: 0,
      bevelSegments: 3, // 斜角分段数
    })

    const material = new THREE.MeshBasicMaterial({
      wireframe: true
    })
    const text = new THREE.Mesh(textGeometry, material)
    scene.add(text)
  })
image.png
  • 如上图所示,当前字体在坐标系中不在居中的位置,three.js提供了简单的居中方法,手动居中的计算方式可参考以下注释的部分,同时可对比2次打印textGeometry.boundingBox的坐标数值
  fontLoader.load(..., (font) => {
    ...
    ...
    textGeometry.computeBoundingBox() // 计算物体边界
    // console.log(textGeometry.boundingBox)

    // 移动物体至坐标系中心
    // textGeometry.translate(
    //   - (textGeometry.boundingBox.max.x - 0.02) * 0.5, // 减去bevelSize
    //   - (textGeometry.boundingBox.max.y - 0.02) * 0.5, // 减去bevelSize
    //   - (textGeometry.boundingBox.max.z - 0.03) * 0.5, // 减去bevelThickness
    // )
    textGeometry.center()
    // console.log(textGeometry.boundingBox)
  })
  • 下一步添加torus的部分,这一步需要注意的是,我们将创建TorusGeometry的部分放在for循环外面,避免频繁创建所造成的性能消耗,可以通过console.time观察不同的写法所消耗的时间
  fontLoader.load(..., (font) => {
    ...
    ...
    ...
    // console.time('donuts')

    // torus
    const donutGeometry = new THREE.TorusGeometry(0.3, 0.2, 20, 45)
    for(let i = 0; i < 100; i++) {
      const donut = new THREE.Mesh(donutGeometry, material)

      donut.position.x = (Math.random() - 0.5) * 10
      donut.position.y = (Math.random() - 0.5) * 10
      donut.position.z = (Math.random() - 0.5) * 10

      donut.rotation.x = Math.random() * Math.PI
      donut.rotation.y = Math.random() * Math.PI

      const scale = Math.random()
      donut.scale.set(scale, scale, scale)
      // 这里特别注意,不能写成这样,xyz坐标值需要保持统一变化
      // donut.scale.set(Math.random(), Math.random(), Math.random()) 
 
      scene.add(donut)
    }
    // console.timeEnd('donuts')
  })
  • 最后,通过TextureLoader加载新的纹理,替换material,删除坐标系
  /*
    * texture
  */
  const textureLoader = new THREE.TextureLoader()
  const matcapTexture = textureLoader.load('../public/imgs/mat-cap-4.jpg')
  fontLoader.load(..., (font) => {
    ...
    ...
    // const material = new THREE.MeshBasicMaterial({
    //   wireframe: true
    // })
    const material = new THREE.MeshMatcapMaterial({
      matcap: matcapTexture
    })
  })
  /**
   * axesHelper
  **/
  const axesHelper = new THREE.AxesHelper(5)
  // scene.add(axesHelper)

相关文章

网友评论

      本文标题:three.js - 3D Text

      本文链接:https://www.haomeiwen.com/subject/cwqzvdtx.html