美文网首页
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