啥是补间动画呢?其实就是我们在threejs中移动一个物体的时候,不让他是瞬时移动,让他跟css动画的transition一样,有个过度效果,就是补间动画。补间动画如何设置呢?
补间动画实现
1.引入补间动画库
在我们的threejs依赖中,就提供了补间动画库tween,因此可以直接在threejs的依赖中引入,也可以下载tween依赖
//导入补间动画库
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
2.创建一个球放入场景中
// 创建一个球
const sphere1 = new THREE.Mesh(
new THREE.SphereGeometry(1, 32, 32),
new THREE.MeshBasicMaterial({
color: 0x00ff00,
})
);
sphere1.position.x = -4;
scene.add(sphere1);
3.给小球添加补间动画 并启动
//补间动画
const tween = new TWEEN.Tween(sphere1.position);
tween.to({ x: 4 }, 1000);
//启动补间动画
tween.start();
这时候我们会发现画布中的小球并没有变化,因为在渲染函数中我们没有更新补间动画
4.渲染函数中更新补间动画
//渲染函数
function animate() {
controls.update();
//请求动画帧
requestAnimationFrame(animate);
//渲染
renderer.render(scene, camera);
//更新补间动画
TWEEN.update();
}
5.补间动画相关操作
1.回调函数
我们可以在补间动画添加回调函数,来进行一系列的操作。
tween.to({ x: 4 }, 1000);
tween.onUpdate(() => {
console.log(sphere1.position);
});
// tween.to({ x: 4 }, 1000).onUpdate(()=>{
// console.log(sphere1.position);
// });
//同上
补间动画的回调函数还有其他的 开始、结束、停止、更新、重复
tween.onStart(() => {
console.log("开始");
});
tween.onComplete(() => {
console.log("结束");
});
tween.onStop(() => {
console.log("停止");
});
tween.onUpdate(() => {
console.log("更新");
});
tween.onRepeat(() => {
console.log("重复");
});
2.其他操作
补间动画也有一些其他的相关操作,比如说循环无数次、延迟进行、循环往复
测试一下循环无数次和延迟进行
//重复循环无数次
tween.repeat(Infinity);
// tween.repeat(3);
// 循环往复
// tween.yoyo(true);
//延迟进行
tween.delay(3000);
当然 我们也可以让他像贝塞尔曲线那样,忽快忽慢的运动,更符合现实,我们用缓动函数来解决。下面这个链接中有threejs曲线的名字,用来带入参数。我们正好测一下往返
tweenjs 曲线参数
//设置缓动函数
tween.easing(TWEEN.Easing.Quadratic.InOut);
// 循环往复
tween.yoyo(true);
3.链式使用
补间动画当然也可以链式使用,两个动画连接使用,我们来创建第二个动画
const tween2 = new TWEEN.Tween(sphere1.position);
tween2.to({ y: -4 }, 1000);
//链接补间动画
tween.chain(tween2);
//启动补间动画
tween.start();
全部代码
//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入补时动画库
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
//导入lil.gui
// import * as dat from "dat.gui"; // 旧
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
45, // 视角
window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
0.1, // 近平面 相机最近最近能看到的物体
1000 // 远平面 相机最远能看到的物体
);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小 (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);
camera.position.z = 15;
// 为了看到z轴
camera.position.y = 2;
// 设置x轴
camera.position.x = 2;
//设置相机的焦点 (相机看向哪个点)
camera.lookAt(0, 0, 0);
//添加世界坐标辅助器 (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(5);
//添加到场景之中
scene.add(axesHelper);
// 添加轨道控制器 (修改侦听位置) 一般监听画布的事件 不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);
//渲染函数
function animate() {
controls.update();
//请求动画帧
requestAnimationFrame(animate);
//渲染
renderer.render(scene, camera);
//更新补时动画
TWEEN.update();
}
animate();
//渲染
// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
// 重新设置渲染器的大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 重新设置相机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 重新计算相机的投影矩阵
camera.updateProjectionMatrix();
});
//创建gui实例
const gui = new GUI();
// 创建一个球
const sphere1 = new THREE.Mesh(
new THREE.SphereGeometry(1, 32, 32),
new THREE.MeshBasicMaterial({
color: 0x00ff00,
})
);
sphere1.position.x = -4;
scene.add(sphere1);
//补时动画
const tween = new TWEEN.Tween(sphere1.position);
// tween.to({ x: 4 }, 1000).onUpdate(()=>{
// console.log(sphere1.position);
// });
//同上
tween.to({ x: 4 }, 1000);
tween.onUpdate(() => {
console.log(sphere1.position);
});
//重复循环无数次
// tween.repeat(Infinity);
// tween.repeat(3);
// 循环往复
// tween.yoyo(true);
//延迟进行
// tween.delay(3000);
//设置缓动函数
tween.easing(TWEEN.Easing.Quadratic.InOut);
//启动补时动画
tween.start();
const tween2 = new TWEEN.Tween(sphere1.position);
tween2.to({ y: -4 }, 1000);
//链接补时动画
tween.chain(tween2);
// 2 链接 1
tween2.chain(tween);
//启动补时动画
tween.start();
tween.onStart(() => {
console.log("开始");
});
tween.onComplete(() => {
console.log("结束");
});
tween.onStop(() => {
console.log("停止");
});
tween.onUpdate(() => {
console.log("更新");
});
tween.onRepeat(() => {
console.log("重复");
});
let params = {
stop: function () {
tween.stop();
}
};
gui.add(params, "stop").name("停止");