(一)动画原理
动画,本质上是一系列图片在特定时间内,以一定频率播放所产生的视觉错觉。这背后依托于人眼的视觉暂留特性,即光象在视网膜形成后,视觉会维持一段有限时间。通常,中等亮度光刺激下,视觉暂留时间约 0.1 至 0.4 秒。为实现连贯、平滑的动画过渡,一般以 60 帧 / 秒甚至更高速率渲染动画。
(二)创建动画
在 three.js 里,我们借助requestAnimationFrame()方法创建动画。由于动画需按频率播放,所以要构建一个循环渲染函数,并加以调用。具体如下:
js
function animate() {
// 在这里进行属性更新等操作
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
上述代码中,animate函数不断循环,每次循环都会调用requestAnimationFrame(animate),让浏览器控制动画帧更新,同时通过renderer.render(scene, camera)将更新后的场景渲染到画布上。
(三)制作动画(在原代码基础上)
假设场景中有一个立方体,我们想让它随时间旋转。可通过如下方式实现:
js
let cube;
// 初始化场景、相机、渲染器等代码省略
function init() {
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
cube = new THREE.Mesh(geometry, material);
scene.add(cube);
}
function animate() {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
init();
animate();
上述代码中,每次animate函数被调用,立方体在 x 轴和 y 轴方向都会分别旋转 0.01 弧度,进而实现连续旋转的动画效果。
二、three.js 相关插件介绍
(一)dat.gui
在开发中,常需频繁调试模型位置、大小等参数,手动在场景内操作既不便捷也不直观。dat.gui 插件则很好地解决了这一问题,它是轻量级图形用户界面插件,能轻松创建可改变代码变量的界面组件,实现实时交互效果。
1. 使用 dat.gui 步骤
- 引入 dat.gui 插件:可通过下载插件文件并在 HTML 中引入,或使用包管理工具安装引入。
- 定义数据对象:
js
const guiData = {
x: 0,
y: 0,
z: 0
};
这里定义了一个包含 x、y、z 三个属性的对象,用于后续控制模型位置。
- 实例化 dat.gui 对象并添加配置:
js
const gui = new dat.GUI();
gui.add(guiData, 'x', -5, 5).onChange((value) => {
cube.position.x = value;
});
gui.add(guiData, 'y', -5, 5).onChange((value) => {
cube.position.y = value;
});
gui.add(guiData, 'z', -5, 5).onChange((value) => {
cube.position.z = value;
});
上述代码中,实例化dat.GUI对象gui,分别为guiData的 x、y、z 属性添加滑动条组件,范围是 - 5 到 5,并且当滑动条值改变时,相应更新立方体的位置。
(二)stats.js
在 three.js 开发中,性能问题不容忽视。stats.js 作为 javascript 性能监视器,可助力检测动画运行帧数,帮助开发者了解程序性能瓶颈。
1. 使用 stats.js 步骤
- 引入 stats.js:下载并在 HTML 中引入。
- 实例化并添加到页面:
js
const stats = new Stats();
document.body.appendChild(stats.dom);
上述代码实例化Stats对象stats,并将其生成的 DOM 元素添加到页面,用于展示性能数据。
- 在渲染循环中更新:
js
function animate() {
stats.begin();
// 动画更新与渲染代码
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
stats.end();
requestAnimationFrame(animate);
}
在animate函数中,每次渲染前调用stats.begin(),渲染后调用stats.end(),以便stats.js准确统计渲染帧数等性能数据。