GSAP

0x01 概述

(1)简介

  • 官网链接:https://gsap.com/

  • GSAP(GreenSock Animation Platform)是一个为专业人员构建的非常健壮的 JavaScript 动画库

  • 特点:

    • 将 JavaScript 可以接触到的任何东西动画化
    • 提供丝滑的性能和无与伦比的支持
    • 专注于动画开发而不必关注底层实现
  • 与 GSAP 旧版本对比:

    GSAP 2 GSAP 3
    核心库 TweenMax.min.js
    TweenLite.min.js
    TimelineMax.min.js
    TimelineLite.min.js
    gsap.min.js
    语法 TweenMax(".circle", 2, { x: 100 });
    var timeline1 = new TimelineMax();
    gsap.to(".rect", { duration: 4, y: 70 });
    let timeline1 = gsap.timeline();

(2)创建项目

以下使用 GSAP 的版本为 3.12.5

a. CDN

  1. 在 index.html 中,导入 GSAP 库

    <head>
      <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
    </head>
    
  2. 创建 main.js

    gsap.to("#container", {
      delay: 1, // 延时 1 秒
      x: 200, // x 轴移动 200px
      y: 100, // y 轴移动 100px
      scaleX: 2, // 放大 x 轴 2 倍
      scaleY: 2, // 放大 y 轴 2 倍
      duration: 1, // 持续时间 1 秒
    });
    
  3. 在 index.html 中导入 main.js

    <body>
      <script src="./main.js"></script>
    </body>
    

b. npm

  1. 使用命令 npm init -y 创建 NodeJS 环境

  2. 使用命令 npm install gsap 安装 GSAP

  3. 在 index.html 中,导入 GSAP 库

    <head>
      <script src="./node_modules/gsap/dist/gsap.min.js"></script>
    </head>
    
  4. 创建 main.js

    gsap.to("#container", {
      delay: 1, // 延时 1 秒
      x: 200, // x 轴移动 200px
      y: 100, // y 轴移动 100px
      scaleX: 2, // 放大 x 轴 2 倍
      scaleY: 2, // 放大 y 轴 2 倍
      duration: 1, // 持续时间 1 秒
    });
    
  5. 在 index.html 中导入 main.js

    <body>
      <script src="./main.js"></script>
    </body>
    

0x02 基本概念

(1)对象

  • GSAP 通过对象的方式调用

    • GSAP 的引用对象是 gsap
  • 举例:获取当前 GSAP 版本

    console.log(gsap.version); // 3.12.5
    

(2)补间(Tween)

  • 补间:通过插值计算,完成静态开始和结束之间所有中间帧属性

  • 补间实例需要提供目标对象持续时间开始帧与结束帧等属性

    • 补间一般语法为:gsap.方法名(目标对象, 持续时间, 其他属性对象),v3 支持将持续时间写在其他属性对象
  • 举例:

    <svg width="900" height="650">
      <rect class="rect" x="400" y="300" width="100" height="100" fill="indigo" stroke="black" />
    </svg>
    
    gsap.to(".rect", {
      duration: 3,
      delay: 1,
      rotate: 2880,
      skewX: 45,
      fill: "yellow",
      ease: "power1.in",
    });	
    
  • 创建补间的方法包括:

    方法 说明
    gsap.to() 设置结束帧,默认当前为开始帧
    gsap.from() 设置开始帧,默认当前为结束帧
    gsap.fromTo() 设置开始帧和结束帧

    举例:

    <head>
      <!-- ... -->
      <style>
        div {
          width: 100px;
          height: 100px;
          margin: 10px;
          border-radius: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          color: white;
        }
      </style>
    </head>
    
    <body>
      <div id="red" style="background-color: red;">to</div>
      <div id="blue" style="background-color: blue;">from</div>
      <div id="green" style="background-color: green;">fromTo</div>
      <script src="./main.js"></script>
    </body>
    
    gsap.to("#red", 3, { delay: 2, x: 500 });
    gsap.from("#blue", 3, { delay: 2, x: 500 });
    gsap.fromTo("#green", 3, { x: 0 }, { delay: 2, x: 500 });
    

(3)时间轴(Timeline)

  • 时间轴:用于创建和管理动画序列的工具

  • 时间轴一般语法为:

    let 时间轴唯一名称 = gsap.timeline(时间轴属性);
    时间轴唯一名称.method(目标对象, 补间属性);
    
  • 举例:

    <head>
      <!-- ... -->
      <style>
        div {
          width: 100px;
          height: 100px;
          margin: 10px;
          border-radius: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          color: white;
        }
      </style>
    </head>
    
    <body>
      <div id="red" style="background-color: red;">to</div>
      <div id="blue" style="background-color: blue;">from</div>
      <div id="green" style="background-color: green;">fromTo</div>
      <script src="./main.js"></script>
    </body>
    
    const timeline = gsap
      .timeline({
        defaults: {
          // 默认属性
          duration: 3, // 持续 3 秒
          ease: "power1.inOut", // 缓动函数
          yoyo: true, // 往返播放
          repeat: -1, // 无限循环
        },
      })
      .to("#red", 3, { delay: 2, x: 500 }, "<1")
      .from("#blue", 3, { delay: 2, x: 500 }, "<1")
      .fromTo("#green", 3, { x: 0 }, { delay: 2, x: 500 }, "<1");
    
  • 动画在时间轴上的定位取值包括:

    取值 说明(数字单位为秒)
    (number)(数字) 绝对时间
    +=(number)-=(number) 相对时间轴终点之后(或之前)
    (label)(文本) 文本
    (label)+=(number) 相对文本
    < 在前一个补间的开始处插入补间
    > 在前一个补间的结束处插入补间
    <(number) 相对最近添加的动画开始处
    >(number) 相对最近添加的动画结束处
  • 动画控制方法包括:

    方法 说明
    play() 开始
    pause() 暂停
    restart() 重启
    seek(time) 跳转至指定 time
    reverse() 反转
    resume() 恢复

    举例:

    <body>
      <!-- ... -->
      <button>click</button>
    </body>
    
    document.querySelector("button").addEventListener("click", () => {
      // timeline.play();
      timeline.pause();
      // timeline.restart();
      // timeline.seek(1);
      // timeline.reverse();
      // timeline.resume();
    });
    

0x03 深入功能

(1)set 方法

  • set() 方法用于设置动画目标对象的属性

    • 一般语法为:gsap.set(目标对象, 属性);
  • 举例:三角形矩阵波浪

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg width="100%" height="100%"></svg>
      <script src="./main.js"></script>
    </body>
    
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    }
    
    // 绘制三角
    class Triangle {
      constructor(id, p1, p2, p3) {
        this.id = id;
        this.p1 = p1;
        this.p2 = p2;
        this.p3 = p3;
    
        this.draw = () => {
          document.querySelector(
            "svg"
          ).innerHTML += `<polygon id="${this.id}" class="triangle" points="${this.p1.x} ${this.p1.y} ${this.p2.x} ${this.p2.y} ${this.p3.x} ${this.p3.y} ${this.p1.x} ${this.p1.y}" fill="red" />`;
        };
      }
    }
    
    // 起始纵坐标
    const p1 = new Point(0, 60.6);
    const p2 = new Point(0, 70.7);
    const p3 = new Point(0, 70.7);
    
    const row = 15,
      col = 27,
      stepX = 30,
      stepY = 30;
    
    for (let i = 0; i < row; i++) {
      p1.x = 77.9;
      p2.x = 61.7;
      p3.x = 94.0;
      let angle = -90;
      for (let j = 0; j < col; j++) {
        new Triangle(`t${j}${i}`, p1, p2, p3).draw();
        
        // 使用 set 方法
        gsap.set(`#t${j}${i}`, {
          transformOrigin: "-50% -50%",
          rotate: angle,
        });
        
        angle += 13.3;
        p1.x += stepX;
        p2.x += stepX;
        p3.x += stepX;
      }
      p1.y += stepY;
      p2.y += stepY;
      p3.y += stepY;
    }
    
    gsap.to(".triangle", 5000, {
      rotate: 360 * 1000,
      repeat: -1,
      ease: "linear",
      stagger: -0.005, // 交错(下一节)
    });
    

(2)交错动画

  • 交错动画用于在一系列目标之间创建时间间隔,以增强视觉效果和性能

  • 交错动画作为属性 stagger 使用,其取值包括:

    类型 说明
    数字 秒数
    对象 配置对象
    函数 对交错的函数逻辑

    其中,配置对象的属性包括:

    属性名 说明
    amount 所有交错动画的总时间
    each 每个子补间开始时间之间的时间
    from 在数组中交错发出的位置
    grid 网格中显示元素的行数和列数
    axis 交错动画坐标轴的配置
    ease 分配动画开始时间的 ease 函数(ease-in 等)

    函数的属性为:

    stagger: (索引, 目标数组中该索引对应的目标, 目标数组) => {
      // 自定义逻辑
      return 延迟时间;
    }
    
  • 举例:

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg width="100%" height="100%"></svg>
      <script src="./main.js"></script>
    </body>
    
    // 绘制圆圈
    function Circle(id, x, y, r) {
      this.id = id;
      this.x = x;
      this.y = y;
      this.r = r;
    
      this.draw = () => {
        document.querySelector(
          "svg"
        ).innerHTML += `<circle id="${this.id}" cx="${this.x}" cy="${this.y}" r="${this.r}" stroke="red" stroke-width="10" stroke-dasharray="100%, 0" fill="transparent" />`;
      };
    }
    
    for (let i = 0; i < 20; i++)
      new Circle("circle", 450, 350, 300 - i * 15).draw();
    
    gsap.to("#circle", 2, {
      delay: 1,
      repeatDelay: 1,
      strokeDasharray: "0,100%",
      yoyo: true,
      ease: "power1.inOut",
      repeat: -1,
      stagger: (index, target, list) => (index % 2 == 0 ? 0.05 : 0.2) * index, // 奇偶圈存在延时差异
    });
    

(3)动画构建逻辑

a. 交互性

  • 原理:通过 JavaScript 的 DOM 操作,将 GSAP 动画逻辑绑定到 DOM 事件中

  • 举例:图形跟随鼠标移动

    <div 
      id="circle"
      style="width: 100px; height: 100px; background-color: rgba(192, 0, 0, 0.3); border-radius: 100%;"
      >
    </div>
    
    document.addEventListener("mousemove", (e) => {
      gsap.to("#circle", {
        x: e.pageX - 60,
        y: e.pageY - 60,
        stagger: 0.1,
        duration: 0.1,
      });
    });
    

b. 递归

  • 原理:通过递归函数的方法,实现函数间循环调用、交错调用等方法

  • 举例:传送门

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg width="100%" height="100%">
        <rect id="rect" width="50" height="50" fill="yellow" x="100" y="100" stroke="black" stroke-width="4" />
      </svg>
      <script src="./main.js"></script>
    </body>
    
    const timeline = gsap.timeline({
      defaults: { duration: 1, ease: "linear" },
    });
    let startX, startY, endX, endY;
    
    function move(times) {
      if (times > 9) return;
    
      timeline.to("#rect", { x: endX - 125, y: endY - 125 });
      timeline.set("#rect", { x: startX - 125, y: startY - 125 });
    
      move(times + 1);
    }
    
    let clickTimes = 0;
    document.addEventListener(
      "click",
      (e) => {
        if (clickTimes === 2) return;
    
        clickTimes++;
        if (clickTimes === 1) {
          startX = e.clientX;
          startY = e.clientY;
          document.querySelector(
            "svg"
          ).innerHTML += `<ellipse cx="${startX}" cy="${startY}" rx="20" ry="50" fill="black" stroke="red" stroke-width="4" />`;
        } else {
          timeline.set(rect, { x: startX - 125, y: startY - 125 });
          endX = e.clientX;
          endY = e.clientY;
          document.querySelector(
            "svg"
          ).innerHTML += `<ellipse cx="${endX}" cy="${endY}" rx="20" ry="50" fill="black" stroke="blue" stroke-width="4" />`;
    
          move(0); // 调用移动函数(递归)
        }
      },
      false
    );
    

0x04 核心插件

(1)AttrPlugin

  • AttrPlugin 用于为 DOM 元素的任何数字属性设置动画

  • 一般语法为:attr: { 属性名: 属性值 },其中:

    • 属性键值对可以有多个
    • 属性名是与 DOM 元素的属性对应的属性的名称
    • 属性值是相应属性的目标数值
  • 举例:SVG 滤镜动画

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg width="100%" height="100%">
        <defs>
          <filter id="tile">
            <feTile id="feTile" in="SourceGraphic" x="0" y="0" width="10" height="10" />
          </filter>
        </defs>
        <image xlink:href="https://images.unsplash.com/photo-1444076095244-6edf09c44c27" height="100%"
          style="filter: url(#tile)" />
      </svg>
      <script src="./main.js"></script>
    </body>
    
    document.addEventListener(
      "mousemove",
      (e) => {
        gsap.set("#feTile", {
          attr: {
            width: e.pageX,
            height: e.pageY,
          },
        });
      },
      false
    );
    

(2)CSSPlugin

a. 一般动画

  • CSS 提供了一些属性如 width 可以被动画化,而 GSAP 的 CSSPlugin 不仅简化了这些属性的动画化语法,还增加了对过滤器等其他属性的动画化

  • 举例:光影动画

    <head>
      <!-- ... -->
      <style>
        * {
          margin: 0;
          padding: 0;
        }
    
        body {
          width: 100vw;
          height: 100vh;
          background-color: black;
          display: flex;
          justify-content: center;
          align-items: center;
        }
    
        p {
          font-size: 300px;
          text-align: center;
          line-height: 200px;
          text-shadow: 10px 10px 4px white;
        }
      </style>
    </head>
    
    <body>
      <p id="text">SRIGT</p>
      <script src="./main.js"></script>
    </body>
    
    document.addEventListener(
      "mousemove",
      (e) => {
        gsap.set("#text", {
          textShadow:
            -(e.pageX - window.innerWidth / 2) / 60 +
            "px " +
            -(e.pageY - window.innerHeight / 2) / 60 +
            "px 2px white, " +
            -(e.pageX - window.innerWidth / 2) / 50 +
            "px " +
            -(e.pageY - window.innerHeight / 2) / 50 +
            "px 30px yellow",
        });
      },
      false
    );
    

b. 2D & 3D

  • 对于 2D 与 3D 属性的同时动画,需要预设好以下属性:

    属性 说明
    transformPerspective 三维空间的畸变量(只影响被动画化的元素)
    transformOrigin 转换发生的支点
  • 举例:

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg width="100%" height="100%">
        <rect id="rect" x="100" y="100" width="200" height="150" fill="red" />
        <circle id="circle" cx="200" cy="200" r="50" fill="pink" />
      </svg>
      <script src="./main.js"></script>
    </body>
    
    gsap.defaults({
      transformOrigin: "50% 50% 200%",
      transformPerspective: 3000,
      ease: "none",
      repeat: -1,
    });
    
    // 形变预设
    gsap.set("#container", { rotateY: 90 });
    gsap.set("#rect", { scale: 0.5 });
    gsap.set("#circle", { scale: 2 });
    
    // 动画设置
    gsap.to("#container", 10, { rotateY: 3600 });
    gsap.to("#rect", 10, { scale: 1, yoyo: true });
    gsap.to("#circle", 10, { scale: 1, yoyo: true });
    

c. 百分比

  • GSAP 支持通过属性 xPercentyPercent 实现百分比变换

  • 举例:

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <button id="btnX">X</button>
      <button id="btnY">Y</button>
    
      <svg id="container" width="100%" height="100%">
        <rect class="rect" x="100" y="100" width="100" height="50" fill="red" />
        <rect class="rect" x="100" y="200" width="75" height="50" fill="blue" />
        <rect class="rect" x="100" y="300" width="50" height="50" fill="pink" />
      </svg>
      <script src="./main.js"></script>
    </body>
    
    document
      .getElementById("btnX")
      .addEventListener("click", () => gsap.to(".rect", 1, { xPercent: "+=100" }));
    
    document
      .getElementById("btnY")
      .addEventListener("click", () => gsap.to(".rect", 1, { yPercent: "+=100" }));
    

d. 旋转

  • 旋转动画由有向旋转原点变化构成

  • 有向旋转一般语法为:rotate: "角度_方向",其中方向的取值包括:

    方向值 说明
    cw 顺时针(clockwise rotation)
    ccw 逆时针(counterclockwise rotation)
    short 自动向最短方向
  • 原点变化的选项包括:

    选项 说明
    transformOrigin 使用元素的本地坐标空间
    svgOrigin 使用 SVG 全局坐标空间
    smoothOrigin 对于 SVG 中元素移动时抽搐的消除优化,即平滑移动
  • 举例:

    <head>
      <!-- ... -->
      <style>
        html,
        body {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
      </style>
    </head>
    
    <body>
      <svg id="container" width="100%" height="100%">
        <defs>
          <linearGradient id="lg" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" stop-color="red" />
            <stop offset="100%" stop-color="yellow" />
          </linearGradient>
        </defs>
        <ellipse id="ellipse" cx="200" cy="100" rx="100" ry="50" fill="url(#lg)" />
      </svg>
      <script src="./main.js"></script>
    </body>
    
    gsap.to("#ellipse", 10, {
      transformOrigin: "50% 50%",
      rotation: "-100_ccw",
    });
    

e. 滤镜

  • CSS 支持对任意非空元素添加一个或多个滤镜

  • 举例:

    <body>
      <img id="img1" src="https://images.unsplash.com/photo-1464820453369-31d2c0b651af" alt="" width="200" />
      <img id="img2" src="https://images.unsplash.com/photo-1464820453369-31d2c0b651af" alt="" width="200" />
      <img id="img3" src="https://images.unsplash.com/photo-1464820453369-31d2c0b651af" alt="" width="200" />
      <img id="img4" src="https://images.unsplash.com/photo-1464820453369-31d2c0b651af" alt="" width="200" />
      <script src="./main.js"></script>
    </body>
    
    document.addEventListener("mousemove", (e) => {
      // 反色
      gsap.set("#img1", {
        filter: `invert(${(e.pageX / window.innerWidth) * 100}%)`,
      });
    
      // 色相
      gsap.set("#img2", {
        filter: `hue-rotate(${(e.pageX / window.innerWidth) * 100 * 10}deg)`,
      });
    
      // 饱和度
      gsap.set("#img3", {
        filter: `saturate(${100 - (e.pageX / window.innerWidth) * 100}%)`,
      });
    
      // 透明与模糊
      gsap.set("#img4", {
        filter:
          `opacity(${(e.pageX / window.innerWidth) * 100}%)` +
          `blur(${(window.innerWidth - e.pageX) / 50}px)`,
      });
    });
    

(3)ModifiersPlugin

  • ModifiersPlugin 用于在原有动画基础上,拦截并修改动画变化方式

  • 修改器的函数参数包括:

    参数 类型 说明
    value 数字或字符串 需要从补间重新计算和应用的属性值
    target 对象 在调用修饰符函数的当前时间进行所有转换的动画的目标
  • 举例:

      <div id="rect" style="width: 100px; height: 100px; background-color: aqua;"></div>
    
    gsap.to("#rect", 5, {
      x: 400,
      y: 200,
      yoyo: true,
      ease: "none",
      modifiers: {
        y: (value, target) => Math.sin(parseFloat(value) / 60) * 300 + 300 + "px",
      },
    });
    

(4)EndArrayPlugin

  • EndArrayPlugin 用于在补间动画结束时执行一个函数数组中的多个回调函数,从而可以在动画结束时依次触发多个操作

  • 举例:

    <head>
      <!-- ... -->
      <style>
        div {
          width: 100px;
          height: 100px;
          margin: 10px;
          border-radius: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          color: white;
        }
      </style>
    </head>
    
    <body>
      <div id="red" style="background-color: red;"></div>
      <div id="blue" style="background-color: blue;"></div>
      <div id="green" style="background-color: green;"></div>
      <script src="./main.js"></script>
    </body>
    
    const array = [0, 100, 150];
    
    gsap.to(array, 10, {
      endArray: [50, 50, 50],
      onUpdate: () => {
        gsap.set("#red", { x: array[0] });
        gsap.set("#blue", { x: array[1] });
        gsap.set("#green", { x: array[2] });
    
        document.getElementById("red").innerHTML = array[0];
        document.getElementById("blue").innerHTML = array[1];
        document.getElementById("green").innerHTML = array[2];
      },
    });
    

(5)SnapPlugin

  • SnapPlugin 用于绑定到预先选择的动画期间动画属性的值

  • 举例:

    <head>
      <!-- ... -->
      <style>
        div {
          width: 100px;
          height: 100px;
          margin: 10px;
        }
      </style>
    </head>
    
    <body>
      <div id="red" style="background-color: red;"></div>
      <div id="blue" style="background-color: blue;"></div>
      <div id="green" style="background-color: green;"></div>
      <script src="./main.js"></script>
    </body>
    
    gsap.to("#red", 10, { x: 400, snap: "x" });
    gsap.to("#blue", 10, { x: 400, snap: { x: 50 } });
    gsap.to("#green", 10, { x: 400, snap: { x: [25, 50, 100, 200, 400] } });
    

0x05 缓动函数

  • GSAP 中的缓动函数用于控制动画的节奏和流畅度,在动画属性 ease 中指定,常见的缓动函数如:

    缓动函数 说明
    linear 匀速缓动
    power0~power4 power0 等同于 linear
    power1~power4 的缓动效果随数字升高而更加剧烈
    elasticbounce power 类似,但是以弹性回弹方式结束
    expo 指数级缓动变化
    cubic 平滑的 power3
    quart 平滑的 power4
    quint power4 类似

    以下以 ExpoScaleEase 为例

  • ExpoScaleEase 用于创建具有指数增长或衰减的动画效果,如模拟自然的缩放动画

    • 在开始和结束时速度较慢,中间速度较快
  • 一般语法为:ease: 'expoScale(开始缩放值, 结束缩放值, 缓动方法)',其中缓动方法可选

  • 举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/EasePack.min.js"></script>
    </head>
    
    <body>
      <img src="https://i0.hdslb.com/bfs/new_dyn/dafa12f3d28739d8f5864570ff227a57385263117.jpg" alt="" width="20%" />
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(EasePack);
    
    gsap.to(document.querySelector("img"), 10, {
      delay: 1,
      scale: 20,
      ease: "expoScale(0.2, 20)",
    });
    

0x06 额外插件

(1)TextPlugin

  • TextPlugin 用于替换 DOM 元素的文本内容

  • 一般语法为:text: 值,其中,的取值可以是 DOM 元素的新文本内容属性对象

  • 当取值为 DOM 元素的新文本内容时,可以实现打字机效果文本替换效果文本消失效果

    举例:文本替换效果

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/TextPlugin.min.js"></script>
    </head>
    
    <body>
      <p style="font-size: 2em;">Hello, I am SRIGT.</p>
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(TextPlugin);
    
    gsap.to(document.querySelector("p"), 10, {
      delay: 1,
      text: "Here is my introduction."
    });
    
  • 当取值为属性对象时,常用属性有:

    属性名 说明
    value 新文本内容
    delimiter 将文本分开的字符
    speed 单位时间内变化次数
    动画持续时间计算方法:\(\frac {0.05}{speed × 新文本长度}\)
    preserveSpaces 处理额外的空格
    padSpace 节省不必要的末端空间
    type 仅对存在差异的文件执行动画
    newClass 应用于新文本的 CSS 类
    oldClass 应用于旧文本的 CSS 类

    举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/TextPlugin.min.js"></script>
      <style>
        .old {
          color: red;
          background-color: aqua;
        }
    
        .new {
          color: aqua;
          background-color: red;
        }
      </style>
    </head>
    
    <body>
      <p class="old" style="font-size: 2em;">This is an old paragraph.</p>
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(TextPlugin);
    
    gsap.to(document.querySelector("p"), 10, {
      delay: 1,
      text: {
        value: "This is a new paragraph.",
        delimiter: "",
        speed: 1,
        preserveSpaces: true,
        padSpace: true,
        type: "diff",
        newClass: "new",
        oldClass: "old",
      },
    });
    

(2)Draggable

  • Draggable 用于使 DOM 元素具有交互功能,如位移、旋转、缩放、形变

  • 一般语法为:Draggable.create(目标元素, 配置对象),其中:

    • 目标元素是被交互的 DOM 元素

    • 配置对象 包括:

      属性 默认值 可取值 说明
      type "x,y" "x,y" "x" "y" "left,top" "left" "top" rotation 拖动时影响的属性
      zIndexBoost true 布尔值 是否允许被拖动元素的 z-index 临时提高到顶部
      bounds HTML 元素对象、选择器字符串、矩形对象(topleftwidthheight)、极大极小对象(maxXmaxYminXminYmaxRotationminRotation 移动限制
      liveSnap - 函数、数组、对象、布尔值 步进
  • Draggable 中有很多方法:

    方法名 说明
    enable() / disable() 允许 / 禁止拖拽功能
    startDrag() / endDrag() 开始 / 结束拖拽动作
    create() / kill() 创建 / 销毁拖拽实例
    update() 对已存在的实例更新参数
    addEventListener() 对拖拽元素添加事件监听
    hitTest() / get() 碰撞检测 / 实例检测
    applyBounds() 用界限来限制可拖拽的运动
    getDirection() 获取拖拽方向
    timeSinceDrag() 上次拖动结束后到现在的时间间隔
    enabled() 获取当前是否允许拖拽
  • 举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/Draggable.min.js"></script>
      <style>
        div {
          width: 100px;
          height: 100px;
          margin: 100px;
          background: linear-gradient(red, blue);
          color: white;
          font-size: 5em;
          text-align: center;
        }
      </style>
    </head>
    
    <body>
      <div id="one">1</div>
      <div id="two">2</div>
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(Draggable);
    
    Draggable.create("#one", {
      onDrag: function () {
        if (this.hitTest("#two"))
          gsap.to(this.target, 1, {
            opacity: 0,
            scale: 0,
            ease: "circ.in",
          });
      },
    });
    

(3)Flip

  • Flip 用于在布局改变时,提供不同状态之间的平滑过渡

  • Flip 由四个单词解释:

    1. First:记录元素当前状态
    2. Last:做出改变
    3. Invert:将偏移量应用于元素的原始状态
    4. Play:通过动画完成上述偏移量
  • 举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/Flip.min.js"></script>
      <style>
        .col {
          display: flex;
          flex-direction: column;
        }
    
        .row {
          display: flex;
          flex-direction: row;
        }
    
        div {
          width: 100%;
          margin: 10px;
          color: white;
          font-size: 5em;
          text-align: center;
        }
      </style>
    </head>
    
    <body class="col">
      <div style="background-color: red;">1</div>
      <div style="background-color: green;">2</div>
      <div style="background-color: blue;">3</div>
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(Flip);
    
    document.addEventListener(
      "click",
      () => {
        const state = Flip.getState(".col, div");
        document.querySelector(".col").classList.toggle("row");
        Flip.from(state, { absolute: true });
      },
      false
    );
    

    其中:

    • Flip.getState(目标元素,其他配置) 用于标记并返回目标元素的状态,

      • 默认情况下,除了尺寸、旋转、倾斜、不透明度、视口中的位置外,其他属性需要在其他配置中写明
    • Flip.from(状态, 动画配置) 用于返回一个时间轴实现动画效果

      动画配置中:

      • absolute: true:通过绝对定位保证动画丝滑变化
      • scale: true:同步缩放
      • nested: true:通过嵌套实现同步计算父子组件的动画

(4)ScrollTrigger

  • ScrollTrigger 用于当目标对象进入视口时触发相应的效果

  • 一般语法为:scrollTrigger: 配置对象,其中配置对象包括多个属性:

    • trigger:选定目标对象

    • toggleActions:行为切换,顺序为 "进入视口时 离开视口时 重新进入视口时 退出视口时",默认为 "play none none none",关键字包括:

      关键字 说明 关键字 说明 关键字 说明 关键字 说明
      play 播放 pause 暂停 resume 恢复 reset 重置
      restart 重启 complete 完成 reverse 翻转 none
    • start:设置起始位置

    • end:设置终止位置

    • markers:是否引入用于测试的标记

    • scrub:采用随滚动进度而步进的动画

  • 举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/ScrollTrigger.min.js"></script>
      <style>
        div {
          width: 100%;
          height: 100vh;
          color: white;
          font-size: 5em;
          text-align: center;
        }
      </style>
    </head>
    
    <body class="col">
      <div id="red" style="background-color: red;">1</div>
      <div id="green" style="background-color: green;">2</div>
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(ScrollTrigger);
    
    gsap.from("#green", 10, {
      opacity: 0,
      scrollTrigger: {
        trigger: "#green",
        start: "top 80%",
        end: "bottom 20%",
        scrub: true,
        markers: true,
      },
    });
    

(5)ScrollToPlugin

  • ScrollToPlugin 用于实现滚动效果

    需要结合 ScrollTrigger 使用

  • 举例:

    <head>
      <!-- ... -->
      <script src="./node_modules/gsap/dist/ScrollTrigger.min.js"></script>
      <script src="./node_modules/gsap/dist/ScrollToPlugin.min.js"></script>
      <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
    
        html,
        body,
        div {
          width: 100%;
          background: linear-gradient(to bottom, black, #010101);
        }
    
        img {
          width: 100%;
          height: 100%;
        }
      </style>
    </head>
    
    <body>
      <img id="moon" src="https://images.unsplash.com/photo-1446941611757-91d2c3bd3d45" alt="" />
      <img src="https://images.unsplash.com/photo-1451187580459-43490279c0fa" alt="" />
      <script src="./main.js"></script>
    </body>
    
    gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
    
    gsap.to("#moon", {
      scrollTrigger: {
        trigger: "#moon",
        start: "0%",
        end: "50%",
        scrub: true,
      },
      scale: 0.25,
    });
    
    document.addEventListener("DOMContentLoaded", () => {
      gsap.to(window, 10, {
        delay: 1,
        scrollTo: {
          y: "max", // 滚动到页面的底部
          autoKill: true, // 允许在开始滚动后更改滚动位置
        },
      });
    });
    

-End-

posted @ 2025-02-07 19:10  SRIGT  阅读(337)  评论(0)    收藏  举报