初探GSAP
时至今日在Web中开发动效有很多种方式,有纯CSS的方式(Animations和Transitions),也有Web Animation API和SVG Animation,还有很多优秀的JavaScript库(比如,Anime.js、KUTE.js、Mo.js等)。在WebGL方面有Three.js、PixiJS、Babylon.js和PlayCanvas等。除此之外,业内还有一个制作动画非常出色的平台,那就是GSAP(GreenSock Animation Platform的简称)。在接下来的日子中,将会不间断的发布一些关于GSAP制作动效相关的教程,今天这篇文章,主要和大家先探讨一些GSAP的基础知识。
W3cplus小站上关于Web动画相关的教程有很多,如果你对动画其他方面的知识感兴趣的话,可以猛击这里进行了解。
GSAP是什么?
GSAP是GreenSock提供的一个制作动画的成熟的JavaScript库,该库源于Flash的动画。这也意味着GreenSock背后的人对Web动画了如指掌,这个库已经存在很长的时间了,而且不会很快消失。
GSAP中有很多工具和插件,我们可以利用它们来快速开发Web动画和快速处理开发Web动画遇到的任何挑战。除了GSAP具有强大的特性、工具和插件之外,而且学习曲线也相对较浅,因为它在所有不同的实现和插件中使用了直观且一致的语法。此外,GSAP论坛还提供了很棒的文档、教程等。
为什么选择GSAP?
文章开头就提到过,在Web中构建中动画效果有很多种方式,也有很多优秀的库或工具,那么为什么要选择GSAP呢?那是因为,GSAP有着下面几个明显的特征:
- 速度快: GSAP专门优化了动画性能,使用实现和CSS一样的高性能动效
- 轻量和模块化: 模块化与插件式的结构保持了GSAP核心引擎的轻量,TweenLite包非常的小。GSAP还提供了 TweenLite、 TimelineLite、 TimelineMax、 TweenMax等功能动画模块,在使用的时候可以按需加载
- 没有依赖: 使用GSAP开发动效时不需要依赖于任何第三方库或插件
- 灵活控制: 不用受限于线性序列,可以重叠动画序列,你可以通过精确时间控制,灵活地使用最少的代码实现动效
- 任何对象都可以实现动画,只要能运行JavaScript脚本的地方就可以使用GSAP
GSAP也非常的灵活,可以适用于你给它的任何东西。也就是,GSAP可以让下面这些东东都动起来:
- CSS: CSS中的
2D
和3D
方面的transform
、color
、width
、opacity
、border-radius
、margin
等,几乎所有的CSS属性都可以 - SVG: SVG中的一些属性,比如
viewBox
、width
、height
、fill
、stroke
、cx
、r
、opacity
等,而且借助像 MorphSVG 和 **DrawSVG**这样的GSAP插件,还可以实现一些高级的效果 - 任何数值,比如
<canvas>
的对象,3D
动画场景中的摄像机位置和滤镜值
一旦你学习了GSAP相关的基本语法,就能够在任何可运行JavaScript脚本的地方使用GSAP。如果你也比较关注DOM元素的CSS属性的动画,在使用GSAP时,还可以在React、Vue等前端框架中使用。
GSAP核心模块
GSAP有几大核心模块,它们是:
- TweenLite:GSAP的基础,一个轻量级和快速的HTML5动画库
- TweenMax:TweenLite的扩展,除了包括TweenLite本身之外,还包括TimelineLite、TimelineMax、CSSPlugin、AttrPlugin、RoundPropsPlugin、DirectionalRotationPlugin、BezierPlugin和EasePack
- TimelineLite:一种轻量级的Timeline,用于控制多个Tween和(或)其他Timeline
- TimelineMax:一个增强版的TimelineLite,它提供了额外的、非必要的功能,如
repeat
、repeatDelay
和yoyo
等等
在实际使用的时候,如果你所需要的功能不是过强,可以直接使用GSAP自己内置的API(TweenLite),但如果你所需要的功能过强的话,可以根据自己的需要加载相应的功能模块。在后面介绍GSAP使用的时候,我们会详细介绍这方面。
值得注意的是,GSAP除了提供上述所列的功能模块之外,还提供了一些额外的功能(也有付费的额外功能),比如使用 DrawSVGPlugin创建线条绘制的动画效果,MorphSVHPlugin可以将一个SVG形状变形为另一个,以及其他功能。
GSAP如何工作?
接下来,我们来通过真实的实例来向大家阐述GSAP是如何工作的。
加载GSAP
如果你要使用GSAP来制作Web动画,那么首先要加载GSAP。加载GSAP的方法有很多种,其中最简单的就是加载一个CDN的地址:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.1/gsap.min.js"></script>
如果你还需要一些其他的功能,还可以点击这里,在CDN选项中选择自己所需要的功能模块:
这个时候会多加载相应功能模块或插件的JavaScript脚本文件:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.1/CSSRulePlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.1/EaselPlugin.min.js"></script>
这种方式和其他制作动画效果的JavaScript库相似。这样一来,就可以在你的页面中使用GSAP来开发动效了。
如果你是使用像React或Vue这样的前端框架来开发Web应用或Web页面的话,可以使用NPM或Yarn来安装:
npm install gsap
安装完gsap
之后,也可以在这里的“Modules/NPM”选项中选择所需要的插件和功能模块:
然后将对应的代码复制到要使用GSAP的页面或组件中:
import { gsap } from "gsap";
import { CSSRulePlugin } from "gsap/CSSRulePlugin";
import { DrawSVGPlugin } from "gsap/DrawSVGPlugin";
gsap.registerPlugin(CSSRulePlugin, DrawSVGPlugin);
如果你像我一样是GSAP的初级使用者,我更建议在Codepen上引入GSAP核心库和所需要的插件及功能模块对应的JavaScript。可以在“CodePen”选项中选择所需要的插件等,并且复制所需的脚本地址:
接下来需要在Codepen新建的页面中的JavaScript设置项中添加所复制的JavaScript文件地址:
这样一来就可以在Codepen使用GSAP开发动画效果了。
就我个人而言,我比较喜欢在Codepen上做一些小Demo的开发,方便而且易于分享。接下来的示例,一般都会在Codepen上开发和展示。
第一个GSAP制作的动画
咱们先用CSS Animation 和 Web Animation API来构建一个简单的动画效果,然后使用GSAP开发出一个等同效果的动画。
比如我们用一个div
绘制了一个圆形,然后给这个圆添加一个简单动效:
向右移动
200px
,并且移动过程中放大2
倍
如果用CSS Animation来构建的话,会使用@keyframes
来声明一个动画:
@keyframes ball {
to {
transform: translateX(200px) scale(2);
}
}
.ball {
animation: ball 2s linear both
}
效果如下:
点击示例中的“Play”按钮,你看到的动画效果如下:
上面的动画效果换成Web Animation API也不复杂:
const ballKeyframes = [
{
transform: 'translateX(0) scale(1)'
},
{
transform: 'translateX(200px) scale(2)'
}
]
const ballOptions = {
duration: 2000,
easing: 'linear',
fill: 'both'
}
const ball = document.querySelector(".ball");
const handlePlay = document.getElementById("play");
const ballAnimation = ball.animate(ballKeyframes, ballOptions)
ballAnimation.pause();
handlePlay.addEventListener("click", () => {
ballAnimation.play();
});
效果如下:
接下来,使用GSAP来实现上面的动画效果。实现这样的一个简单地动画效果,我们只使用GSAP的核心功能就可能了,它自身就带有一些实现动画效果的API,比如其中的gsap.to()
、gsap.fromTo()
和gsap.from()
等。
const handlePlay = document.getElementById("play");
const tween = gsap.to(".ball", {
duration: 2,
x: 200,
scale: 2,
paused: true
});
handlePlay.addEventListener("click", () => {
tween.play();
});
效果如下:
最后的效果和前面使用CSS Animation和Web Animation API是等同的:
你打开浏览器开发者工具,你会发现点击示例中的“Play”按钮之后,会发现div
元素会动态加载一个行内样式style
,就该示例而言是transfrom
属性的值在不断的变化,最终停止在gsap.to()
设置的值:
<div class="ball" style="transform: translate(200px, 0px) scale(2, 2);"></div>
你可能发现了,这个最终值和前面示例中@keyframes
中的to{}
中的值是相同的。
特别声明,你可能还不太了解GSAP中的
gsap.to()
方法的使用,但不用过于担心,阅读到后面,你会了解GSAP中内置的一些方法、属性等实际含义和作用!
GSAP基本API
我们来看几个常用的API。
gsap.to()
在上面的示例中,用的就是gsap.to()
方法:
gsap.to(".ball", {
duration: 2,
x: 200,
scale: 2,
paused: true
});
gsap.to()
中的第一个参数.ball
是需要动起来的元素(在该示例中,就是div.ball
元素),第二个参数是一个object
,该对象中是用来设置元素动画的一些属性。比如:
x
:相当于CSS的transform: translateX()
,即元素在x
轴移动scale
:相当于CSS的transform: scale()
,即元素放大或缩小duration
:相当于CSS的animation-duration
,动画播放的持续时间paused
:是设置动画的状态
在object
中可以是控制元素样式的属性参数,也可以是控制动画的一些属性参数,比如:
x: 100 // ──> transform: translateX(100px)
y: 100 // ──> transform: translateY(100px)
z: 100 // ──> transform: translateZ(100px)
scale: 2 // ──> transform: scale(2)
scaleX: 2 // ──> transform: scaleX(2)
scaleY: 2 // ──> transform: scaleY(2)
scaleZ: 2 // ──> transform: scaleZ(2)
skew: 15 // ──> transform: skew(15deg)
skewX: 15 // ──> transform: skewX(15deg)
skewY: 15 // ──> transform: skewY(15deg)
rotation: 180 // ──> transform: rotate(180deg)
rotationX: 180 // ──> transform: rotateX(180deg)
rotationY: 180 // ──> transform: rotateY(180deg)
rotationZ: 180 // ──> transform: rotateZ(180deg)
perspective: 1000 // ──> transform: perspective(1000px)
transformOrigin: '50% 50%' // ──> transform-origin: 50% 50%
上面我们看到的是CSS中transform
中对应的一些CSS属性,其实在gsap.to()
中可设置的属性还可以是其他的CSS属性。换句话说,可以运用于animation
和transition
中的CSS属性都可以运用于gsap.to()
中。比如:
gsap.to('element', {
backgroundColor: 'red',
borderRadius: 15
})
除了在gsap.to()
中可以运用改变元素特性的CSS属性之外,还可以是控制动效的一些CSS属性,比如:
duration: 2 // ──> animation-duration: 2s
delay: 1 // ──> animation-delay: 1s
ease: 'linear' // ──> animation-timing-function: linear
repeat: 2 // ──> animation-iteration-count: 2
除了这些能和CSS属性对应上的之外,还有一些其他的属性,比如immediateRender
、lazy
、onComplete
、overwrite
、repeatDelay
等,有关于这方面更详细的介绍,可以查阅gsap.to()
官方文档。
gsap.from()
gsap.from()
可以用来设置动画元素动画开始的位置(结束的位置是元素当前状态,即动画元素在屏幕上的状态)。可能这样不太好理解,我们用Animation.css中的slideInLeft
动画效果:
@keyframes slideInLeft {
from {
transform: translate3d(-100%, 0, 0);
visibility: visible;
}
to {
transform: translate3d(0, 0, 0);
}
}
用gsap.from()
就可以很好的实现一个类似的动画效果:
const handlePlay = document.getElementById("play");
const tween = gsap.from(".ball", {
duration: 2,
x: "-100vw",
visibility: "visible",
paused: true
});
handlePlay.addEventListener("click", () => {
tween.play();
});
效果如下:
点击示例中的“Play”按钮,球会从屏幕外移进来:
注意,能用于
gsap.to()
的属性和方法同样可以运用于gsap.from()
。
gsap.from()
和gsap.to()
如果将两个结合起来,就能实现动画对象从哪里到哪里,其中gsap.from()
是用来指定动画对象开始的状态,gsap.to()
是用来指定动画对象结束的状态。比如下面这个示例:
const tween = gsap.from(".item", {
opacity: 1,
x: 10,
y: -30,
rotate: 45,
duration: 1,
paused: true
});
const tween2 = gsap.to(".item", {
opacity: 1,
x: -30,
y: 0,
rotate: 0,
borderRadius: "50%",
backgroundColor: "rgb(42 173 210)",
duration: 4,
delay: 1,
paused: true
});
效果如下:
gsap.fromTo()
GSAP中还有一个gsap.fromTo()
方法,它允许你定义动画对象初始状态和结束状态。相当于gsap.from()
和gsap.to()
两个方法的结合物。比如上面的示例,我们可以用gsap.fromTo()
来实现:
const tween = gsap.fromTo(".item",
{
opacity: 1,
x: 10,
y: -30,
rotate: 45
},
{
opacity: 1,
x: -30,
y: 0,
rotate: 0,
borderRadius: "50%",
backgroundColor: "rgb(42 173 210)",
duration: 4,
paused: true
}
);
playAni.addEventListener("click", () => {
tween.play();
});
restartAni.addEventListener("click", () => {
tween.restart();
});
效果如下:
gasp.set()
如果你想立即设置一些属性,可以使用gasp.set()
方法。其实它的本质就是一个持续时间为0
到gsap.to()
的补间动画。比如下面两个方法,实现的动画效果是一样的:
gsap.set(".class", {x: 100, y: 50, opacity: 0.5});
gsap.to(".class", {duration: 0, x: 100, y: 50, opacity: 0.5});
gsap.defaults()
和gsap.config()
GSAP中的gsap.defaults()
方法你设置所有补间动效所需要的参数。比如,如果你想改变所有补间动效的ease
和duration
,可以像下面这样做:
gsap.defaults({
ease: "power2.in",
duration: 1
});
但如果你在特定的补间动画中重新显式设置了与gsap.defaults()
相同的属性,则会覆盖,比如:
gsap.to('.class',{
ease: 'linear',
duration: 2
})
有的时候,使用GSAP制作动效,需要做一些统一的配置,比如说单位的处理,那么就可以使用GSAP中的gsap.config()
方法:
gsap.config({
autoSleep: 60,
force3D: true,
nullTargetWarn: false,
units: {
x: "vw",
y: "vh"
}
});
gsap.config()
主要有autoSleep
、force3D
、nullTargetWarn
和units
等配置选项,有关于这几个配置详细的说明,可以查阅官方文档。
gsap.timeline()
时间线(Timeline)是一个强大的时序控制工具,它包括了Tweens和时间线容器,使用它可以简单地控制多个动画之间的时间。如果没有Timeline的话,构建复杂的序列动画就会很麻烦,因为只能靠每个动效的延迟时间和持续时间来控制,比如:
gsap.to("#id", {x: 100, duration: 1});
gsap.to("#id", {y: 50, duration: 1, delay: 1});
gsap.to("#id", {opacity: 0, duration: 1, delay: 2});
为了更好的理解,还是从我们最熟悉的CSS动画开始:
<div class="container">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
/* CSS */
@keyframes dot {
0% {
transform: translateY(0) scale(1);
}
25% {
transform: translateY(100px) scale(1.1);
}
50% {
transform: translateY(0) scale(0.9);
}
75% {
transform: translateY(-100px) scale(1.1);
}
100% {
transform: translateY(0) scale(1);
}
}
.play .dot {
animation: dot 1s linear both;
}
.play .dot:nth-child(1) {
animation-duration: 1s;
animation-delay: 0s;
}
.play .dot:nth-child(2) {
animation-duration: 1s;
animation-delay: 1s;
}
.play .dot:nth-child(3) {
animation-duration: 1s;
animation-delay: 2s;
}
效果如下:
这三个.dot
的动画时序如下图所示:
如果你点击了示例中的“Play”按钮,动画效果如下:
在GSAP中,我们可以使用gasp.timeline()
实现一个类似的效果:
const blue = document.querySelector(".blue");
const pink = document.querySelector(".pink");
const yellow = document.querySelector(".yellow");
const tl = gsap.timeline();
tl.to(blue, { scale: 2 })
.to(blue, { rotation: 360 })
.to(blue, { scale: 1 })
.to(pink, { y: -50 })
.to(pink, { rotation: 360 })
.to(pink, { y: 0 })
.to(yellow, { scale: 0.5 })
.to(yellow, { rotation: 360 })
.to(yellow, { scale: 1 });
效果如下:
Timeline是一个复杂的体系,在后续的内容中将会花更多的时间和大家一起来探讨这方面的知识。
GSAP控制动画的方法
在Web Animation API中Animation
提供了多个方法用来控制动画,比如cancel()
、finish()
、pause()
、play()
等。在GSAP中,同样有一些类似的方法,用来控制动画。
// 创建一个动画
let tween = gsap.to('.ball',{duration: 1, x: 100}); // 或 gsap.timeline(...) 创建动画;
// GSAP控制动画的方法
tween.play() // ──> 播放
.pause() // ──> 暂停
.resume() // ──> 继续播放
.reverse() // ──> 反方向播放
.restart() // ──> 重新播放
.timeScale(2) // ──> 2 = 两倍速度, 0.5 = 半速
.seek(1.5) // ──> 跳转到时间(秒)或标签
.progress(0.5) // ──> 跳转到一半
.totalProgress(0.8) // ──> 包括重复
// 当用作setter时,返回动画(链)
// 其他有用的方法 (tween 和 timeline)
.kill() // ──> 立即销毁
.isActive() // ──> 如果当前正在播放动画,返回true
.then() // ──> Promise
.invalidate() // ──> 清除记录的开始、结束值
.eventCallback() // ──> 获取或设置一个事件回调
// timeline:具体方法
// add 标签, tween, timeline 或 callback
.add(thing, position)
// 在指定点调用函数
.call(func, params, position)
// 获取时间轴的子元素数组
.getChildren()
// 空的timeline
.clear()
// 动画播放头到一个位置线性
.tweenTo(timeOrLabel, {vars})
// ^^ 有开始和结束的位置
.tweenFromTo(from, to, {vars})
我们来看一个简单的地示例:
var tween = gsap.to(".green", {
duration: 4,
x: 750,
rotation: 360,
borderRadius: '50%',
backgroundColor: '#f36',
boxShadow: '0 0 10px 20px #f90',
ease: "none",
paused: true
});
document.querySelector("#play").addEventListener('click', () => tween.play())
document.querySelector("#pause").addEventListener('click', () => tween.pause())
document.querySelector("#resume").addEventListener('click', () => tween.resume())
document.querySelector("#reverse").addEventListener('click', () => tween.reverse())
document.querySelector("#restart").addEventListener('click', () => tween.restart())
效果如下:
GSAP中的缓动函数
在CSS的animation
和transition
中可以使用animation-timing-function
和transition-timing-function
来指定动效的缓动效果。简单地说就是用来控制动效在过渡期间的变化速度。在CSS的animation
和transition
中有几个固定的缓动函数,即linear
、ease
、ease-in
、ease-in-out
、ease-out
和cubic-bezier()
等。
在GSAP中,控制动效的缓动函数ease
要强大的多,除了常见的函数之外,还可以使用下面这个交互工具,获取更多的缓动函数:
来看一个简单地示例:
document.querySelector("#bounce").addEventListener("click", () => {
gsap.to("#logo", {
duration: 1,
y: 100,
scale: 0.5,
ease: "bounce"
});
});
document.querySelector("#linear").addEventListener("click", () => {
gsap.to("#logo", {
duration: 1,
x: 100,
scale: 0.8,
ease: "linear"
});
});
document.querySelector("#elastic").addEventListener("click", () => {
gsap.to("#logo", {
duration: 1,
y: 100,
x: 30,
scale: 0.5,
ease: "elastic.out(1, 0.3)"
});
});
document.querySelector("#circ").addEventListener("click", () => {
gsap.to("#logo", {
duration: 1,
y: 100,
scale: 1.2,
ease: "circ.out"
});
});
document.querySelector("#expo").addEventListener("click", () => {
gsap.to("#logo", {
duration: 1,
y: 100,
x: 100,
scale: 0.5,
ease: "expo.out"
});
});
效果如下:
小结
如果你阅读到这里的话,我想你对GSAP有了一个初步的认识。
这篇文章中,介绍了GSAP的一些基础知识,通过对这些基础知识的了解,已经可以使用GSAP的一些基本API,比如,gsap.to()
、gsap.from()
、gsap.fromTo()
;一些控制动画的方法,比如play()
、restart()
等,还有Timeline以及缓动函数等来构建一个简单地动画效果。正如文章中所说的,GSAP的功能是非常强大的,只要我们掌握GSAP核心模块的知识,我们制作动画效果就能如鱼得水。如果你对这方面感兴趣的话,请持续关注后续相关内容的更新。在后面将会和大家一起探讨GSAP中更深奥知识,比如Timeline,TweeLite、TweenMax等。
最后希望这篇文章对你有所帮助,如果你在这方面有更多的经验或建议,欢迎在下面的评论中与我们一起共享。