2024年,手把手教你使用GSAP制作页面动画-基础概念篇

1,041 阅读8分钟

前言

本篇文章面向于第一次接触 GSAP 的前端小伙伴。GSAP 是我个人认为目前市面上比较好上手且功能强大的动画库了。

可惜的是官方文档没有中文翻译,对于一些小伙伴来说阅读非常不友好,可能会对一些概念认识比较模糊。

今天第一篇就来给大家捋一捋一些基础的概念,方便大家后续更好的看懂官方文档。

文章会大量用到官方的代码例子,官方地址:docsHome | GSAP | Docs & Learning

叠甲:因为我个人也是正在学习这个库,边学边写的,如果有错误,欢迎评论区指正~

基本概念

可以开着官方的这个简单代码例子:codepen.io/GreenSock/p… 跟着下面的讲解自己尝试,能更好理解概念。

Tween

翻译过来是 “补间动画”,第一次接触这个词可能不太好理解,我们可以理解成 “从一种状态过渡到另一种状态过程中,所补充的中间变化动画”。

例如一个文字默认/初始状态是 16px 的大小,我们给它设置了一秒后它是一个 32px 大小的最终状态,那在从 16px 变成 32px 大小的这一秒过程中所展现出的逐渐放大的过渡动画就是补间动画。

其中的默认/初始状态、最终状态,有点类似于视频制作或者PPT制作里的 “关键帧”,所以我建议咱们就把状态理解成关键帧,关键帧之间的过渡动画就理解成补间动画。

状态 = 关键帧,过渡动画 = 补间动画

从 gsap 提供的语法来看,既有描述补间动画的动作指导,也有描述关键帧。我拿官方的例子来说明:

gsap.to(".circle", { x: 40, fill: 'blue', });

这个意思为让 gsap 把类名为 .circle 的所有元素,从原来的位置向 x 轴移动 40px,并且填充色变成蓝色。你看,to 就是补间动画的动作指导,从A帧(默认状态)到B帧,{ x: 40, fill: 'blue', } 就是关键帧B的描述。

gsap.from(".circle", { x: -40, fill: 'blue', });

这个的补间动画指导变成了 from,意思是从 { x: -40, fill: 'blue', } 的关键帧变成我们 css 写的默认状态。

gsap.fromTo( ".circle",{ x: -40, fill: 'blue', }, { x: 40, fill: 'green' });

这个就是从 { x: -40, fill: 'blue', } 关键帧到 { x: 40, fill: 'green' } 关键帧。

gsap.set(".circle", { x: 40, fill: 'blue', });

现在的补间动画指导是 set,意思是立马给 .circle 元素设置一个无过渡的关键帧,你将看不到初始状态,直接展示现在的状态 { x: 40, fill: 'blue', }

作用对象选择

明白了这些概念后,咱们来看看动画作用的指定对象,上面是通过 CSS 选择器的方式去指定的:.circle ,咱们也可以通过 DOM 对象数组去指定多个对象:

let square = document.querySelector(".square");
let circle = document.querySelector(".circle");
                                      
gsap.to([square, circle], { x: 200 })

关键帧的定义

关键帧能够定义哪些东西呢?基本就是 CSS 的 transformsopacitybackgroundColor 等属性。不过官方说为了页面绘制性能考虑,建议尽量用 transformsopacity 来设置关键帧来保证性能。

可根据官方给出的表格(我这里就不贴来占篇幅了):gsap.com/resources/g…

此外,对于目标为 SVG 的图片设置关键帧时,比较特殊,可以设置 SVG 一些特有的属性。例如官方给出的例子:

gsap.to(".svgBox", { 
  duration: 2,
  x: 100,
  attr: { // 这个就是 SVG 特有属性
    fill: '#8d3dae',
    rx: 50, 
  },
});

Easing

这个词我不知道咋翻译准确,不过可以理解为 “动画过渡曲线”。

来讲两个概念你就明白了,“线性动画” 和 “非线性动画”,如果一个物体从A移动到B,用的是线性动画,那么我们将看到物体匀速的从A运动到B。如果用的是非线性动画,那么我们可能看到的是物体先从A慢慢加速,然后再慢慢减速最后停在B。后者看起来动画会更加灵动自然。

如果以时间为 x 轴,速度为 y 轴,线性动画的坐标图就是一条直线,非线性动画因为加入了一些加速度的实时变化,所以看起来就会是曲线。

GSAP 允许我们在关键帧中设置动画过渡曲线,至于你想设置成什么类型的曲线,可以看官方的这块地方:gsap.com/resources/g…

右边选择动画曲线,其中左下角圈起来的按钮很重要,可以切换不同视图去感受不同曲线动画带来的效果!

如果你不知道选哪个好,就用它吧 power1.out,官方推荐。

Staggers

好吧,这个词也不好翻译,我理解为 “个体间开启运动的时差”。也是在关键帧定义里设置的。

例如页面中有5个类名为 .box 的元素,我们把关键帧设置为:

gsap.to('.box', {
    y: 100,
    stagger: 0.1 // 这是新加的个体间运动时差
});

那么,这5个元素运动的时候不会是同时开始,而是第一个先触发补间动画,过0.1秒后第二个触发动画,过0.1秒后第三个触发动画,以此类推。配合着非线性动画,让整体看起来更加灵动。

如果你是想实现卡片布局动画或者类似照片墙的那种动画,那么可以详细设置 stagger 这个参数,它可以是一个配置对象:

gsap.to('.box', {
    y: 100,
    stagger: {
        grid: [4, 5],
        each: 0.1,
        // amount: 1, 
        from: 'center', 
        ease: 'power2.inOut',
        axis: 'x',
        repeat: -1 
    }
});

配置说明如下:

  • grid:例子里 [4, 5] 是告诉GSAP,你的列表有4行5列,它会进行精确动画计算,如果你无法确定数量,也可以设置为 'auto' 让它自己算(但每当页面 resize 后,咱们需要重新执行以便更新计算)。
  • each:这个是原来我们填的个体间运动时差。
  • amount: 如果我们设置这个,表示所有个体运动时差的总和,例如有十个物体,就会自动给每个分配0.1秒,同时each就不需要我们设置了。
  • from :表示动画播放的起始位置,有 "start", "center", "edges", "random", "end"
  • axis:表示动画播放的方向,默认不填的话是同时以XY方向播放,也可以指定 'x' 或者 'y'
  • ease:动画过渡曲线,很奇怪我在这里设置无效,在 stagger 外设置才行。
  • repeat:如果设置了,就是个体完成自己的动画后会自行重播,设置在 stagger 外则是所有个体都完成动画后再整体重播。

如果觉得我讲的抽象,可以看看官方这个案例:codepen.io/GreenSock/p…

官方还提到,不要局限于列表(网格)布局的页面,任何布局都可以用上这个 stagger 来增添动画。

Timelines

这个就好翻译了,“时间线”。当你需要设置多个关键帧的时候就需要它了,它的作用就是让你排布关键帧的顺序。例如官方例子:

// 先创建一个时间线
let tl = gsap.timeline()
// 依次排布关键帧
tl.to(".green", { x: 600, duration: 2 }); // A
tl.to(".purple", { x: 600, duration: 1, delay: 1 }); // B
tl.to(".orange", { x: 600, duration: 1 }); // C
// 也可以连续起来写
tl.to(".green", { x: 600, duration: 2 })
.to(".purple", { x: 600, duration: 1, delay: 1 })
.to(".orange", { x: 600, duration: 1 }); 

效果就是A先播放2秒,完成后B立马播放1秒,完成后等个1秒,紧接C立马播放1秒。

GSAP 还提供了更加多样的时间线设置。

tl.to(".class", {x: 100}, 3); // 一般放在最开头,表示页面进来后3秒再开始执行
tl.to(".class", {x: 100}, "+=1"); // 表示之前时间线上的所有关键帧中,最后一个完成播放的关键帧它的1秒后再播放
tl.to(".class", {x: 100}, "<"); // 表示和上一个关键帧同时播放
tl.to(".class", {x: 100}, "+=50%"); // 表示先等待自身动画播放时间的50%后再开始播放动画,一般建议设置一个duration做精确控制

同时时间线也可以做一些全局的配置:

let tl = gsap.timeline({
    repeat: -1, 
    repeatDelay: 1, 
    yoyo: true, 
    defaults: {duration: 1}
})

表示这条时间线正序播放完再倒序播放,然后等1秒后重复播放,并且给每个关键帧默认设置补间动画时间为1秒(在后续的关键帧定义中就不需要再设置)。

Plugins

这是给 GSAP 能力拓展的插件,有免费的也有付费的。

例如很多手机官网喜欢用的鼠标滚动页面触发动画加载插件:ScrollTrigger

例如有设置 SVG 移动路线的插件:MotionPathPlugin

更多可看:滚动触发 |总体规划计划 |文档与学习 --- Plugins | GSAP | Docs & Learning

以后的文章中再详细的讲这块。

尾巴

应该还有不少概念还没讲到,后续我继续学习,把剩下的给补上~