Gsap 3.x 动画基本应用

Posted 记不起的回忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gsap 3.x 动画基本应用相关的知识,希望对你有一定的参考价值。

常用动画

gsap.to(targets, vars)
产生从初始位置(或状态)到目标位置(或状态)的动画
targets: 产生动画的对象
vars: 目标状态参数

gsap.from(targets, vars)
从设置位置(或状态)到初始位置(或状态)的动画
targets: 产生动画的对象
vars: 设置状态参数

gsap.fromTo(targets, vars, vars)
产生从开始位置(或状态)到结束位置(或状态)的动画
targets: 产生动画的对象
vars(第1个): 开始状态参数
vars(第2个): 结束状态参数

// 该动画从100的位置移动到300的位置
gsap.fromTo("div",  
  x: 100 
, 
  duration: 5, 
  x: 300 
);

targets: 设置动画的对象,可以是“.class”、“id”等选择器文本(GSAP内使用document.querySelectorAll(), 具体可参考该用法),也可以是对元素、泛型对象甚至对象数组。
vars: 包含要设置动画的所有属性/值的对象,以及任何特殊属性,如ease、duration、delay或onComplete(如下所列)。

vars参数详解

callbackScope: 用于所有回调(onStart、onUpdate、onComplete等)的范围(this句柄)。在所有回调中this默认指向该tween。若设置callbackScope ,this则指向该设置对象。
data: 将任意数据赋给该属性(字符串或对象引用等),以便可以在任何地方tween.data访问该数据。
delay: 动画开始前的延迟量(秒)。
duration: 动画持续的时间(秒)。默认值:0.5
ease: 动画的运动方式。比如“elastic”(弹性), “strong.inOut”(强烈的先快后慢)等,默认值:“power1.out”(渐缓)
id: 为tween实例分配id(可选),以便之后使用gsap.getById()来获取该tween。

例子:

// 在2秒后,向右移动100
gsap.to("div", 
  id: "myTween",
  delay: 2, 
  duration: 2, 
  x: 100,
  ease: "strong.inOut"
)

immediateRender: false(默认)
通常在不设置delay(延迟)的情况下,tween会在下一帧进行渲染,如果设置为true, 将会强制它在实例化时立即呈现。默认值:false。
由于gsap.from和gsap.fromTo 他们需要从一个状态开始运动,初始状态需要在实例化时立即渲染呈现。
所以在它们的fromvars 中immediateRender是默认为true, 而在gsap.to的vars中默认为false。

例子:

// 当immediateRender为false时,不立即渲染到起始位置,而等到2秒延迟后,才从起始位置开始运动。 
// 而设置true时,则在实例化时就立即渲染到起始位置。
gsap.from("div",  
  delay: 2, 
  x: 500, 
  immediateRender: false 
)

inherit: 通常tween的属性从其所属timeline的defaults继承而来,但是可以通过设置inherit:false来禁止继承, 具体可参考gsap.defaults详解
onComplete: 动画完成时调用的函数。
onCompleteParams: 传递给onComplete函数的参数数组。
例子:

gsap.to("div",  
  x: 500, 
  onComplete: complete, 
  onCompleteParams: [2, "str"] 
) 

function complete(i, str) 
  //i = 2, str = "str" 

repeat: 设置动画重复的次数。 设置1为重复两次, 默认值:0。设置-1为无限重复。
例子:

let tween = gsap.to("div",  
  x: 500, 
  repeat: 2 
);
// 该动画共运动了3次

repeatDelay: 每次动画重复之间等待的时间(秒)。默认值:0
repeatRefresh: 设置true 会导致重复的动画失效,因为每次完成一次后,会重新更新其开始和结束值。如果属性使用的动态值(随机或函数),会得到特别的动画效果。默认值:false。

// 如果设置repeatRefresh:true后则看起来只会重复一次。
// 因为每次重复都会重新更新开始和结束值,第2次重复时起始值更新为500,结束值也是500。
// 所以第2次到第5次位置未发生任何变化。
gsap.to("div",  
  x: 500, 
  repeat: 5, 
  repeatRefresh: true 
);
// 从0位置向右移动一个随机位置,重复5次。关于random的用法请参考gsap.utils详解。
gsap.to("div",  
  x: "random(200, 500)", 
  repeat: 5 
);
// 如果设置repeatRefresh:true后每次重复都会重新计算随机值,div会连续做5次运动,每次运动的距离随机。
// 这就产生了特别的动画效果,所以设置repeatRefresh:true 就特别适合该类型的动画效果。
gsap.to("div",  
  x: "random(200, 500)", 
  repeat: 5, 
  repeatRefresh: true 
);

onRepeat: 当动画重复时调用的函数。需要设置repeat(大于0)才会有效。
onRepeatParams: 传递给onRepeat 函数的参数数组。
onReverseComplete: 当动画从反方向再次达到开始位置时要调用的函数。需要设置reversed: true
onReverseCompleteParams: 传递给onReverseComplete函数的参数数组。
onStart: 动画开始时要调用的函数。
onStartParams: 传递给onStartParams函数的参数数组。
onUpdate: 每次动画更新时(每帧)调用的函数。
onUpdateParams: 传递给onUpdate函数的参数数组。
overWrite: 如果设置true, 该对象的其他动画(任何属性)就会被停止;如果设置auto,只会停止其他动画的相关属性动画;如果false,则不停止任何动画,最后呈现的动画效果是各个动画相互作用的结果。 默认值:false

例子:

gsap.to("div",  x: 500,  y: 500)

gsap.to("div",  x: 300,  overwrite: false)

// 如果设置false(或不设置),2个动画都正常运行,div的x值是2个动画相互作用的结果。
// 如果设置true, 直接会停止第一个动画(x,y的动画都会被停止),最终呈现的是x运动到300,而y没有变化(不会运动到500)。
// 如果设置auto, 只会停止第一个动画的x动画,对于y的动画不受影响,最终呈现的是x运动到300,y运动到500。

paused: 如果设置true,动画将在创建时立即暂停。默认值:false
例子:

let tween = gsap.to("div",  
  x: 500, 
  paused: true 
); 
tween.play();

reversed: 如果设置true,动画将调转方向超其开始方向移动。由于开始已经是初始位置,设置true后动画将显示为暂停。默认值:false。
例子:

gsap.to("div",  
  delay: 2, 
  duration: 2, 
  x: 500, 
  onComplete: function() 
    this.reversed(true); 
   
);

runBackwards: 如果设置true, 动画将翻转其起始值和结束值,但对于ease不会反转。可以通过设置true将gsap.to 转换为gsap.from。默认值:false。
例子:

// 等同于 gsap.from
gsap.to("div",  
  x: 500, 
  runBackwards: true, 
);

stagger: 如果是多个动画目标,可以通过设置类似stagger:0.1(每个目标动画开始之间间隔0.1秒)来错开每个动画。或可以设置参数对象来实现更高级的动画效果,具体参考staggers详解。
例子:

// 所有的div都向右移动500,每个div间隔0.2秒开始移动。
gsap.to("div",  
  x: 500, 
  stagger: 0.2 
);

startAt: 定义任何属性的起始值(即便它们没有设置动画)。
例子:

gsap.to("div",  
  x: 500, 
  startAt:  
    y: 500, 
    alpha: 0.5 
   
);

yoyo: 如果设置true,则每隔一次的重复都将以反方向的方向运动,动画呈现来回运动的效果。单次运动无效,需要配合repeat使用。默认值:false。
例子:

gsap.to("div",  
  x: 500, 
  repeat: 5, 
  yoyo: true 
);

yoyoEase: 允许你改变yoyo过程中的ease。可以指定特定的ease(例如:“power2.in”),可以设置true来翻转原本的ease。默认值:false。 另外:启动了该属性后,yoyo会自动设置true。
例子:

// 如果不设置yoyoEase:true,yoyo过程应该是逐渐加快,设置后原本的ease进行了翻转,变为逐渐减慢。
gsap.to("div",  
  x: 500, 
  repeat: -1, 
  yoyoEase: true 
);
// 这里对yoyo过程设置了一个弹性的ease。
gsap.to("div",  
  x: 500, 
  repeat: -1, 
  yoyoEase: "elastic" 
);

keyframes: 对同一对象的一连串的动画(关键帧动画)。和一连串的gsap.to等效。
例子:

// 沿x轴向右运动100,停顿1秒,再沿x轴向右运动到200的位置,同时y轴运动到200
gsap.to("div",  
  keyframes: [ 
     
      x: 100 
    , 
     
      delay: 1, 
      x: 200, 
      y: 200 
     
  ] 
);

vars 属性的Function类型参数

通过使用function类型参数来实现更复杂的动画效果。
参数:
index: 当前运动对象的索引
target:当前运动对象
targets: 全部运动对象的数组
例子:

// 每个div的运动的y值不同,按顺序依次多100。第一个div运动到x:100, y:0的位置,第2个div运动到x:100,y:100的位置,第3个div运动到x:100,y:200的位置,依次类推。
gsap.to("div",  
  x: 100, 
  y: function(index, target, targets) 
    return index * 100; 
   
);
// 偶数索引的div沿y轴运动100,其他div则y保持不变。
gsap.to("div",  
  x: 100, 
  y: function(index, target, targets) 
    return index % 2 === 0 ? 100 : 0; 
   
);

前端每日实战:144# 视频演示如何用 D3 和 GSAP 创作一个集体舞动画

技术图片

效果预览

按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。

https://codepen.io/comehope/pen/gdVObN

可交互视频

此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。

请用 chrome, safari, edge 打开观看。

https://scrimba.com/p/pEgDAM/caRLack

源代码下载

每日前端实战系列的全部源代码请从 github 下载:

https://github.com/comehope/front-end-daily-challenges

代码解读

定义 dom,容器中包含 2 个子容器,.horizontal 代表水平的线段,.vertical 代表垂直的线段,每个子容器中包含 4 个子元素:

<div class="container">
    <div class="horizontal">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div class="vertical">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>

居中显示:

body {
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: skyblue;
}

设置容器尺寸,其中 --side-length 是方阵的每一边的元素数量:

.container {
    --side-length: 2;
    position: relative;
    width: calc(40px * calc(var(--side-length)));
    height: calc(40px * calc(var(--side-length)));
}

用 grid 布局排列子元素,4 个元素排列成 2 * 2 的方阵:

.container .horizontal,
.container .vertical {
    position: absolute;
    top: 0;
    left: 0;
    display: grid;
    grid-template-columns: repeat(var(--side-length), 1fr);
}

设置子元素的样式,.horizontal 内的子元素是横条,.vertical 内的子元素是竖条:

.container .horizontal span {
    width: 40px;
    height: 10px;
    background: #fff;
    margin: 15px 0;
}

.container .vertical span {
    width: 10px;
    height: 40px;
    background: #fff;
    margin: 0 15px;
}

至此,静态布局完成,接下来用 d3 批量处理子元素。
引入 d3 库:

<script src="https://d3js.org/d3.v5.min.js"></script>

删除掉 html 文件中的子元素 dom 节点,删除掉 css 文件中声明的 css 变量。
定义方阵每一边的元素数量,并把这个数值赋给 css 变量:

const SIDE_LENGTH = 2;

let container = d3.select(‘.container‘)
    .style(‘--side-length‘, SIDE_LENGTH);

定义一个添加 span 子元素的函数,分别添加横向和竖向的子元素:

function appendSpan(selector) {
    container.select(selector)
    .selectAll(‘span‘)
    .data(d3.range(SIDE_LENGTH * SIDE_LENGTH))
    .enter()
    .append(‘span‘);
}

appendSpan(‘.horizontal‘);
appendSpan(‘.vertical‘);

此时,布局已改为动态的,可以通过修改 SIDE_LENGTH 的值来创建不同边长的方阵,比如以下语句将创建 5 * 5 的方阵:

const SIDE_LENGTH = 5;

接下来用 GSAP 创建动画。(注:因 scrimba 在使用 gsap 时会崩溃,所以视频演示采用 css 动画,但 codepen 和 github 均采用 gsap 动画)
引入 GSAP 库:

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

声明动画变量 animation,声明代表 dom 元素的变量 $horizontalSpan$verticalSpan

let animation = new TimelineMax({repeat: -1});
let $horizontalSpan = ‘.container .horizontal span‘;
let $verticalSpan = ‘.container .vertical span‘;

先创建横条的动画,共分成 4 步,每个 to 语句的最后一个参数是步骤的名称:

animation.to($horizontalSpan, 1, {rotation: 45}, ‘step1‘)
    .to($horizontalSpan, 1, {x: ‘-10px‘, y: ‘-10px‘}, ‘step2‘)
    .to($horizontalSpan, 1, {rotation: 0, x: ‘0‘, y: ‘0‘, scaleY: 2, scaleX: 0.5}, ‘step3‘)
    .to($horizontalSpan, 1, {rotation: 90, scaleY: 1, scaleX: 1}, ‘step4‘)

再创建竖条的动画,to 语句的步骤名称与横条的步骤名称相同,以便与横条保持动画同步:

animation.to($verticalSpan, 1, {rotation: 45}, ‘step1‘)
    .to($verticalSpan, 1, {x: ‘10px‘, y: ‘10px‘}, ‘step2‘)
    .to($verticalSpan, 1, {x: ‘0‘, y: ‘0‘, scaleX: 2, scaleY: 0.5}, ‘step3‘)
    .to($verticalSpan, 1, {rotation: 90, scaleX: 1, scaleY: 1}, ‘step4‘);

在动画的末尾用时间尺度缩放函数让动画播放速度加快一倍:

animation.timeScale(2);

最后,把方阵的边长改为 10,方阵越大就越有气势:

const SIDE_LENGTH = 10;

大功告成!

以上是关于Gsap 3.x 动画基本应用的主要内容,如果未能解决你的问题,请参考以下文章

GSAP库解决复杂动画

使用 GSAP 在滚动上为 SVG 设置动画

TweenMax的GSAP(GreenSock动画平台)GSAP,专业的Web动画库

javascript animation lib greensock gsap介绍

在Vue中使用GSAP完成动画(三)动画事件

在Vue中使用GSAP完成动画(四)播放组件