初识 gsap.js 动画库
Three 中的 Clock
之前我们学习了 three.js
我们也写了一个基础方法让他进行移动旋转等类似的动画
function render() {
renderer.render(scene, camera);
cube.position.x += 0.01
if(cube.position.x > 5){
// 我们刚刚设置的坐标轴是5,那么这里设置当他大于5的时候,给他的坐标轴重置
cube.position.x = 0
}
// 浏览器自带方法,在刷新的时候自动执行某个函数↓
requestAnimationFrame(render);
}
但是这个封装的函数有一个问题是
他每一帧的刷新间隔的时间是不一样的
我们在 render 函数里面添加一个参数 time 并把它打印出来
这时候我们可以发现他们之间的时间是不一样的,有的会多一些时间,有的会少一些时间
如果我们想要物体进行匀速移动,该怎么办呢
这时候我们就需要 three 中的一个构造函数 clock 出场了
先 new 一个时钟的构造对象
const clock = new THREE.Clock()
可以传入以下参数
但是目前我们暂时不需要往里传入参数
新构造出来的对象里面有一些方法
getElapsedTime 是获取运行的总时长
getDelta 这个是获取两次获取时间的间隔
即使用了 getElapsedTime 或 getDelta 这两个方法的时间间隔
这时候我们把 render 方法改造一下,这样可以实现我们之前实现过的效果
且还是我们所期望的匀速运动,不随着帧率的改变而改变
function render() {
renderer.render(scene, camera);
// 获取运行的总时长,因为我们没有传入参数,所以默认就是构造出 Clock 对象的时候开始计时
let time = clock.getElapsedTime()
// 两次获取时间的间隔时间
// let deltaTime = clock.getDelta()
// 拿到他运行的时间求取 5 的余数
let t = time % 5
cube.position.x = t * 1
// 浏览器自带方法,在刷新的时候自动执行某个函数
requestAnimationFrame(render);
}
gsap 动画库
引入 gsap
这时候有人就说了,每次都这样子手撕动画,这样未免也太蠢了吧
一点都不符合我们程序员的风格
有没有轮子已经弄好的,我给他加进去就不用在写一大堆耦合的代码了
答案是有的
那就是今天的主角 gsap 动画库
首先我们在对应的文件夹下面进入终端安装该依赖
npm i gsap
之后我们在 main.js 文件里面引入这个动画库
import gsap from "gsap";
我们先不了解他的全部语法,先把它用起来
使用
先来看看他的一个语法
第一个参数是一个目标对象
第二个参数是目标对象的一个属性名持续时间
gsap.to(target, {
x: 200,
duration: 2
})
了解了这个,那我们就在 render 函数上面添加动画库的对应函数
// 我们需要移动的是位置,所以第一个参数放置物体的位置属性对象
// 接下来,我们要让物体沿着 x 轴移动5个单位,持续5秒,就填入以下参数
gsap.to(cube.position, {
x: 5, duration: 5})
// 我们需要移动还有角度,所以第一个参数放置物体的角度属性对象
// 接下来,我们要让物体沿着 x 轴旋转360°,持续5秒,就填入以下参数
gsap.to(cube.rotation, {
x: 2 * Math.PI, duration: 5})
有了这个的话,接下来我们就再不用去手撕动画函数了
render 函数也就干净清爽了很多
gsap.to(cube.position, {
x: 5, duration: 5})
gsap.to(cube.rotation, {
x: 2 * Math.PI, duration: 5})
function render() {
renderer.render(scene, camera);
// 浏览器自带方法,在刷新的时候自动执行某个函数↓
requestAnimationFrame(render);
}
属性
既然是动画嘛,想必很多人也想到了动画速度中的贝塞尔曲线
关于贝塞尔曲线,想了解的人可以先看看这个,到时候我看看有时间的话写篇关于贝塞尔曲线的文章
当然了,这个 gsap 当中也有贝塞尔曲线
他的属性是 ease
官网的举例代码是这样的
gsap.to(graph, {
duration: 2.5, ease: "power2.out", y: -500 });
详情可以参考官网举的例子
速度我们调节好了,接下来如果我想要进行动画的循环,那么应该添加什么属性呢
那就是 repeat 了
repeat 是指的循环的次数,当他是 -1 的时候,会进行无限次的循环
如果我想要对旋转动画无限次的循环就是这样子写
// 旋转动画
gsap.to(cube.rotation, {
x: 2 * Math.PI,
duration: 5,
ease: "power4.inOut",
repeat: -1,
});
既然我们循环了这个动画,那么我想要让动画反着进行播放可以嘛
那自然也是可以的
只需要添加一个 yoyo 属性
比如说我现在要让移动的动画往返,就是这样子写的
gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power4.out",
repeat: -1,
yoyo: true,
yoyoEase: true,
});
可能有人会看到说,欸,你这个 yoyoEase 是什么属性,添加进去是干什么的呢
yoyoEase 这个属性,根据字面意思来,就是把 ease 这个贝塞尔曲线也进行循环
因为这里的 yoyo 在 repeat 的判断里面是走完一个往返,才能够加一次的次数
但是如果一次往返算一次,那么这个动画肯定是不对的
那么就添加了一个 yoyoEase 属性
让动画在返回的时候这个贝塞尔速度曲线重新执行一次
就是你过来的时候动画是啥样的,那么返回的时候动画也是啥样的
这样子更符合人们的直觉
还有许多的动画相关的东西
例如我想要在动画的开始和结束的时候进行调用一个钩子函数
回调函数
- onComplete:动画完成时调用。
- onStart:动画开始时调用
- onUpdate:每次动画更新时调用(在动画处于活动状态时每帧调用)。
- onRepeat:每次动画重复时调用一次。
- onReverseComplete:动画反转后再次到达其起点时调用。
var tween = gsap.from("#app", {
duration: 5,
x: 500,
ease:"elastic.in(1,1)",
onComplete:function () {
// 动画播放完成时调用
console.log("111");
}
});
回调参数
var tween = [gsap.to](http://gsap.to/)("#app", {
duration: 1,
x: 100,
onComplete: tweenComplete,
onCompleteParams: ["done!"]
});
function tweenComplete(message) {
console.log(message);
}
使用上面这种方式调用回调函数时,如果需要传递参数,必须以数组方式传递,即使只有一个参数。
还有如果我需要控制动画的暂停与否或者其他的一些行为
那么我们可以写以下函数
- tween.pause(); 暂停
- tween.resume(); 恢复
- tween.reverse(); 反向播放
- tween.seek(0.5); 跳到0.5s
- tween.progress(0.25); 跳到4分之1处
- tween.timeScale(0.5); 速度减慢
- tween.timeScale(2); 速度翻倍
- tween.kill(); 删除动画
window.addEventListener('click',() => {
// 判断是否动画处于执行状态
if(animate1.isActive()){
// 暂停
animate1.pause()
} else {
// 恢复
animate1.resume()
}
})
以上是这篇文章的内容
希望对你们有所帮助,如果可以的话希望顺路来看看我的博客哦
新的博客
以前的博客
那么我们下集再见啦~