别再写死静态文字了!Vue3+Three.js 实现超酷3D流光旋转文字科技感拉满!【附完整源码】

204 阅读3分钟

前一段时间搞了大量的 Cesium 的内容,现在公司这个部分的项目告一段落。

但是又来了一个搞3D的项目,所以打算后面一段时间更新一下 ThreeJs 相关的内容,有兴趣的朋友可以关注一下。

QQ20260506-102802.gif

核心技术栈

整个效果实现超简洁,核心就靠这几个工具:

使用 Three.js 的3D可视化核心库,负责场景、相机、渲染、3D模型创建。

增加OrbitControls轨道控制器,实现鼠标交互。

最后用TextGeometry3D文字几何体,快速生成立体文字模型。

完整代码

先安装Three.js依赖pnpm i three,除此之外还需要准备一个字体包的json文件。

Three本身自带了几个字体包,可以去 node_modules/three/examples/fonts,此路径下的几个 json 文件 都是。

还可以下载 ttf字体包,通过 gero3.github.io/facetype.js… 进行转换。

<template>
  <div ref="containerRef" class="canvas-container"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as THREE from 'three'
// 引入字体加载器,用于加载3D文字字体文件
import { FontLoader } from 'three/addons/loaders/FontLoader.js'
// 引入3D文字几何体构造器
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js'
// 引入轨道控制器:实现鼠标拖拽、平移、缩放
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

const containerRef = ref(null)

let scene        // 场景
let camera       // 相机
let renderer     // 渲染器
let textMesh     // 3D文字网格模型
let animationId  // 动画帧ID,用于取消监听
let controls     // 鼠标轨道控制器

/**
 * 初始化 three.js 基础环境
 * 创建场景、相机、渲染器、灯光、鼠标控制器
 */
function init() {
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x0a0a1a)
  camera = new THREE.PerspectiveCamera(
    50,
    containerRef.value.clientWidth / containerRef.value.clientHeight,
    0.1,
    1000
  )
  camera.position.z = 200

  // 创建WebGL渲染器,开启抗锯齿
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(containerRef.value.clientWidth, containerRef.value.clientHeight)
  containerRef.value.appendChild(renderer.domElement)

  const ambientLight = new THREE.AmbientLight(0xffffff, 0.6)
  scene.add(ambientLight)

  const directionalLight = new THREE.DirectionalLight(0x409eff, 1)
  directionalLight.position.set(30, 30, 30)
  scene.add(directionalLight)

  controls = new OrbitControls(camera, renderer.domElement)
  // 开启阻尼效果:拖拽有惯性,手感更丝滑
  controls.enableDamping = true

  // 自定义鼠标按键行为
  controls.mouseButtons = {
    LEFT: THREE.MOUSE.ROTATE,  // 左键拖拽 = 旋转视角
    MIDDLE: THREE.MOUSE.DOLLY, // 滚轮 = 缩放远近
    RIGHT: THREE.MOUSE.PAN     // 右键拖拽 = 平移画布
  }
}

/**
 * 创建3D立体文字模型
 * 加载字体、生成文字几何体、绑定材质、居中、加入场景
 */
function create3DText() {
  const loader = new FontLoader()

  loader.load(
    '/font/AlimamaShuHeiTi.json',
    (font) => {
      const textGeo = new TextGeometry('你好,ThreeJs', {
        font: font,                // 绑定加载好的字体
        size: 22,                  // 文字字号大小
        height: 10,                // 文字拉伸厚度(立体程度)
        curveSegments: 16,         // 曲线分段数,数值越高文字越圆润
        bevelEnabled: true,        // 开启倒角(文字边缘圆润)
        bevelThickness: 2,         // 倒角厚度
        bevelSize: 0.8,            // 倒角大小
        bevelOffset: 0,            // 倒角偏移量
        bevelSegments: 5           // 倒角分段
      })

      const textMaterial = new THREE.MeshPhongMaterial({
        color: 0x00ccff,                // 主体基础色(浅蓝)
        emissive: 0xff22aa,             // 自发光颜色(粉紫渐变光)
        emissiveIntensity: 0.8,         // 发光强度 0 ~ 2
        specular: 0xffffff,             // 高光白色
        shininess: 100,                 // 高光锐度
      })

      textMesh = new THREE.Mesh(textGeo, textMaterial)
      textGeo.computeBoundingBox()
      textGeo.center()
      scene.add(textMesh)
    }
  )
}

function animate() {
  animationId = requestAnimationFrame(animate)

  // 3D文字 水平自动旋转:仅Y轴旋转(左右水平转动)
  if (textMesh) {
    textMesh.rotation.y += 0.008
  }

  // 更新控制器阻尼效果
  controls.update()
  // 渲染当前场景和相机画面
  renderer.render(scene, camera)
}
</script>

总结

其实这个3D文字效果还是比较简单的,核心就是用FontLoader加载字体JSON文件。

然后用TextGeometry生成立体文字几何体,最后给个材质。

鼠标控制部分不用实现,OrbitControls轨道控制器全给实现完了。

最后记得用requestAnimationFrame持续更新一下画面,还有就是卸载页面的时候把相应的场景等等信息也销毁掉。