前一段时间搞了大量的 Cesium 的内容,现在公司这个部分的项目告一段落。
但是又来了一个搞3D的项目,所以打算后面一段时间更新一下 ThreeJs 相关的内容,有兴趣的朋友可以关注一下。

核心技术栈
整个效果实现超简洁,核心就靠这几个工具:
使用 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... 进行转换。
html
<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持续更新一下画面,还有就是卸载页面的时候把相应的场景等等信息也销毁掉。