初识 gsap.js 动画库

初识 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 });

详情可以参考官网举的例子

Getting Started with GSAP

速度我们调节好了,接下来如果我想要进行动画的循环,那么应该添加什么属性呢

那就是 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()
  }
})

以上是这篇文章的内容

希望对你们有所帮助,如果可以的话希望顺路来看看我的博客哦
新的博客
以前的博客

那么我们下集再见啦~

猜你喜欢

转载自blog.csdn.net/Vixcity/article/details/128719306