简介
在three.js
中动画也是很重要的一环。在使用软件创建模型时,一般都会创建模型的骨骼动画用于在开发中使用。下面我们加载.fbx
格式的文件模型(它除了包含几何、材质信息,可以存储骨骼动画等数据)来实现动画。
AnimationMixer
- 动画混合器是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。
- 参数:
rootObject
混合器播放的动画所属的对象。就是包含动画模型的场景对象。 - 常用参数和属性:
.time
全局的混合器时间。.clipAction(AnimationClip)
返回所传入的剪辑参数的AnimationAction
对象。AnimationAction
用来调度存储在AnimationClip
中的动画。
AnimationClip
动画剪辑,是一个可重用的关键帧轨道集,它代表动画。
.getRoot()
返回混合器的根对象。.update()
推进混合器时间并更新动画。在渲染函数中调用更新动画。
开始使用
基础场景
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>学习</title>
</head>
<body>
<canvas id="c2d" class="c2d" width="1000" height="500"></canvas>
<script type="module">
import * as THREE from './file/three.js-dev/build/three.module.js'
import { OrbitControls } from './file/three.js-dev/examples/jsm/controls/OrbitControls.js'
import { FBXLoader } from './file/three.js-dev/examples/jsm/loaders/FBXLoader.js'
const canvas = document.querySelector('#c2d')
// 渲染器
const renderer = new THREE.WebGLRenderer({ canvas })
const fov = 40 // 视野范围
const aspect = 2 // 相机默认值 画布的宽高比
const near = 0.1 // 近平面
const far = 10000 // 远平面
// 透视投影相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
camera.position.set(1000, 500, 1500)
camera.lookAt(0, 0, 0)
// 控制相机
const controls = new OrbitControls(camera, canvas)
controls.update()
// 场景
const scene = new THREE.Scene()
// 背景
scene.background = new THREE.Color(0x87ceeb)
// 雾
scene.fog = new THREE.Fog(0x87ceeb, 200, 10000)
// 辅助
const axes = new THREE.AxisHelper(700)
scene.add(axes)
{
// 灯光
const skyColor = 0xffffff // 天空 白色
const groundColor = 0x000000 // 地面 黑色
const intensity = 1
const light = new THREE.HemisphereLight(skyColor, groundColor, intensity)
scene.add(light)
}
{
// 地面
const loader = new THREE.TextureLoader()
const texture = loader.load('./file/23/1.jpg')
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.magFilter = THREE.NearestFilter
// 纹理 重复
texture.repeat.set(100, 100)
const planeGeo = new THREE.PlaneGeometry(10000, 10000)
const planeMat = new THREE.MeshPhongMaterial({
map: texture,
side: THREE.DoubleSide
})
const mesh = new THREE.Mesh(planeGeo, planeMat)
mesh.rotation.x = Math.PI * -0.5
scene.add(mesh)
}
// 渲染
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
</script>
</body>
</html>
加载.fbx模型
const loader = new FBXLoader()
loader.load('./file/Naruto.fbx', function (mesh) {
console.log(' AnimationMixer 动画混合器(二十四).html ~ line 73 ~ mesh', mesh)
mesh.position.y = 110
scene.add(mesh)
})
- 可以看见解析出来的对象中,存在
animations
属性并且有27条数据,代表有27个动画。
使用AnimationMixer控制动画
1.创建全局参数获取动画相关对象。
let actions = [] // 所有的动画数组
let gui = {} // 动画控制
let mixer = null // AnimationMixer 对象
2.解析动画,并执行第24个动画。
mixer = new THREE.AnimationMixer(mesh)
for (var i = 0; i < mesh.animations.length; i++) {
actions[i] = mixer.clipAction(mesh.animations[i])
}
gui['action'] = function (s) {
for (var j = 0; j < actions.length; j++) {
if (j === s) {
actions[j].play()
} else {
actions[j].stop()
}
}
}
// 第24个动作是鸣人站立的动作
gui['action'](24)
- 在渲染函数中执行
.update()
函数,推进动画进行。
.Clock()
该对象用于跟踪时间。
const clock = new THREE.Clock()
// 渲染
function render() {
const time = clock.getDelta()
if (mixer) {
mixer.update(time)
}
renderer.render(scene, camera)
requestAnimationFrame(render)
}
通过键盘空格切换动画
- 监听键盘事件,调用
gui
对象执行新的动画。
let keyNum = 24 // 动作
document.onkeydown = function (e) {
if (e && e.keyCode == 32) {
if (keyNum === 27) {
keyNum = 1
}
keyNum += 1
gui['action'](keyNum)
}
}