学习:GSAP

什么是 GSAP

GSAP(GreenSock Animation Platform)是一个高性能的 JavaScript 动画库,用来让 DOM 元素、SVG、Canvas 甚至 Three.js 对象动起来。它的优势在于:

  • 语法极简:一行代码就能描述一个完整动画。
  • 性能强 :内部用 requestAnimationFrame,且自动做性能优化。
  • 兼容好:支持几乎所有现代浏览器,甚至老 IE。
  • 控制力强:可暂停、倒放、调速、监听回调(后续章节展开)。

一、基本使用

如何引入 GSAP

最简单的方式是通过 CDN 引入一个脚本文件。引入后,全局变量 gsap 即可使用:

javascript 复制代码
<!-- 通过 CDN 引入(需要联网) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>

<!-- 之后即可在任意脚本中使用 gsap -->
<script>
  gsap.to(".box", { x: 200, duration: 1 });
</script>

gsap.to() --- 动画"到"目标状态

gsap.to(target, vars) 表示从元素当前状态 动画到 vars 里描述的目标状态。这是用得最多的方法。

javascript 复制代码
<div class="box" id="toBox"></div>
<script>
  function runTo()   { 
    gsap.to("#toBox", {
      x: 300,          // 向右平移 300px
      rotation: 360,  // 旋转一圈
      duration: 1.2,    // 持续 1.2 秒
      ease: "power2.out"
        }); 
    }
</script>

② gsap.from() --- 从指定状态"回到"当前

gsap.from(target, vars) 的反向写法:让元素 vars 描述的状态,动画到它原本的样子。非常适合做「入场动画」------比如元素从上方淡入落到原位。

javascript 复制代码
<div class="box blue" id="fromBox"></div>
<script>
function runFrom()   {  
    gsap.from("#fromBox", {
      y: -80,         // 从上方 80px 处开始
      opacity: 0,       // 从透明开始
      duration: 1,
      ease: "back.out(1.7)"
    });
}
</script>

③ gsap.fromTo() --- 明确指定起点与终点

gsap.fromTo(target, fromVars, toVars) 同时接收起点终点两个对象,最精确、最可控。当你必须保证动画从某个确定值开始时用它。

javascript 复制代码
<div class="box pink" id="fromToBox"></div>
<script>
  function runFromTo()   {
 gsap.fromTo("#fromToBox",
  { x: 0,   scale: 0.3, opacity: 0 },   // 起点
  { x: 300, scale: 1,   opacity: 1,     // 终点
    duration: 1.2, ease: "power3.out" }
); }
</script>

目标(target)可以怎么写

第一个参数 target 非常灵活,支持多种形式:

写法 说明
"#id" / ".class" CSS 选择器字符串
element 直接传 DOM 元素,如 document.querySelector(".box")
[el1, el2] 元素数组,可同时动画多个
".box, #title" 逗号分隔的复合选择器
javascript 复制代码
<div class="row">
    <div class="box"
       id="m1"></div>
    <div class="box blue"
       id="m2"></div>
    <div class="box pink"
       id="m3"></div>
    </div> 
<script>
 function runMulti() { gsap.to(["#m1", "#m2", "#m3"], { y: 50, rotation: 180, duration: 0.9, stagger: 0.15 }); }
 </script>

最常用的动画属性

GSAP 几乎能补间任何数值型 CSS 属性。下面是最常用的一批(无需写单位,GSAP 会自动处理):

属性 作用
x / y 平移(像素),等价于 transform: translate
rotation 旋转(角度)。rotationX/Y 为 3D 旋转
scale 缩放。scaleX / scaleY 分开控制
opacity 透明度 0~1
duration 动画时长(秒),必会属性
delay 延迟多少秒后开始
ease 缓动曲线,决定快慢节奏(第 2 章重点)
repeat 重复次数,-1 为无限循环
yoyo 配合 repeat,来回往返播放

往返循环

javascript 复制代码
<div class="box" id="propBox"></div>
<script>
 function runProp() { 
    gsap.to("#propBox", {
      x: 300,
      duration: 1,
      ease: "sine.inOut",
      repeat: -1,   // 无限重复
      yoyo: true     // 来回往返
}); }
</script>

二、缓动与交错

同样的位移,不同的「速度节奏」会带来完全不同的观感。

什么是缓动(ease)

如果不设置 ease,GSAP 默认用 power1.out,动画会先快后慢。缓动描述的是属性值随时间变化的曲线:是匀速、先慢后快、还是带弹性回弹?

常用缓动一览

缓动 观感
none 匀速直线运动,最生硬
power1/2/3/4.out 逐渐减速,最常用、自然
sine.inOut 柔和的正弦曲线
expo.out / circ.out 极快起步、长尾缓停
back.out(1.7) 冲过头再回弹,有弹性
elastic.out(1,0.3) 弹簧般来回振荡
bounce.out 像球落地一样弹跳
javascript 复制代码
<div class="box" id="easeBox"></div>
<script>
  function runEase() {
    const ease = document.querySelector("#easeSel").value;
    gsap.fromTo("#easeBox", { x: 0 }, { x: 320, duration: 1.2, ease });
  }
</script>
sine.inOut
back.out(1.7)
elastic.out(1,0.3)
bounce.out

交错动画 stagger

当目标是一组元素时,stagger 让它们依次错开开始,而不是同时动。传一个数字表示每个元素之间的间隔秒数。

javascript 复制代码
<div class="row" id="staggerRow">
            <div class="box"></div><div class="box"></div><div class="box"></div>
            <div class="box"></div><div class="box"></div><div class="box"></div>
 </div>
<script>
function runStagger() { 
    gsap.from("#staggerRow .box", {
      y: -40, opacity: 0, duration: 0.6,
      stagger: 0.12   // 每个元素间隔 0.12 秒
    });
 }
</script>

stagger 的进阶写法

stagger 还可以是对象,控制方向、总量、起止位置:

参数 作用
each 每个间隔秒数(等价数字写法)
amount 总时长,由 GSAP 自动均分间隔
from 起始位置:"start"/"center"/"end"/"edges"
grid 二维网格 [行,列],用于网格状交错
javascript 复制代码
 <div class="row" id="staggerGrid" style="display:grid;grid-template-columns:repeat(5,1fr);gap:10px">
            <div class="box blue"></div><div class="box blue"></div><div class="box blue"></div><div class="box blue"></div><div class="box blue"></div>
            <div class="box blue"></div><div class="box blue"></div><div class="box blue"></div><div class="box blue"></div><div class="box blue"></div>
 </div>

<script>

  function runGrid() { gsap.from("#staggerGrid .box", { scale: 0, opacity: 0, duration: 0.5, stagger: { each: 0.08, from: "center", grid: [2, 5] } }); }
</script>

from: "center" 让中心元素最先动,向四周扩散------很适合做卡片/按钮组的入场。

  • ease 决定动画快慢节奏,默认 power1.out
  • out 系列最常用最自然;back/elastic/bounce 带弹性趣味
  • stagger 让一组元素错开播放,数字即间隔秒数
  • 对象写法可控制 from/grid/amount,实现网格与方向化交错

三、时间线 Timeline

当动画一多,用一堆独立的 gsap.to() 很难控制先后顺序。时间线 gsap.timeline() 像一个「导演」,把多个动画按顺序/重叠地编排在一起,还能整体播放、暂停、倒放。

基本用法

gsap.timeline() 创建时间线,然后像 gsap 一样链式调用 .to() / .from() / .fromTo()。每个动画默认「接在上一个之后」。

javascript 复制代码
<div class="box" id="tlBox"></div>
<script>

  function runTL() {
    if (tl) tl.kill();
    tl = gsap.timeline();
  tl.to("#tlBox", { x: 240, duration: 0.8 })   // 1) 向右
  .to("#tlBox", { y: -40, duration: 0.6 })   // 2) 接在上一个之后向上
  .to("#tlBox", { rotation: 360, duration: 0.8 }); // 3) 再旋转
  }
</script>

用 defaults 统一默认参数

创建时间线时可传入 defaults,里面的属性会被所有子动画继承,减少重复书写。

javascript 复制代码
const tl = gsap.timeline({ defaults: { duration: 0.6, ease: "power2.out" } });
tl.to("#a", { x: 100 })   // 自动用上面的 duration / ease
  .to("#b", { y: 80 });

位置参数:精确控制时间点

每个子动画还可接收第三个参数------位置参数,用来指定它在时间线上的位置,打破「默认接在后面」的规则:

写法 含义
""(省略) 接在上一个动画结束之后(默认)
"<" 与上一个动画同时开始
"<0.3" 在上一个开始后 0.3 秒
"-=0.4" 比默认位置提前 0.4 秒(重叠)
"+=0.5" 比默认位置延后 0.5 秒(留空隙)
"myLabel" 跳到名为 myLabel 的标签处

重叠播放示例

"-=0.4" 让第二个动画与第一个重叠 0.4 秒,过渡更连贯:

javascript 复制代码
<div class="box blue" id="posBox">
<script>

  function runPos() {
    if (tlPos) tlPos.kill();
    tlPos = gsap.timeline();
    tlPos.to("#posBox", { x: 240, duration: 0.8 })
         .to("#posBox", { rotation: 360, duration: 0.8 }, "-=0.4");
  }

</script>

标签(labels):给时间点起名

.addLabel("名字") 在时间线上打标记,之后动画可定位到该标签,方便做「分支/回跳」。

javascript 复制代码
const tl = gsap.timeline();
tl.to(box, { x: 200 })
  .addLabel("turn")          // 在此处打标签
  .to(box, { rotation: 180 }, "turn") // 跳到 turn 处开始
  .to(box, { y: -60 }, "turn+=0.2");

时间线也能整体控制

时间线本身也是一个「动画对象」,可以设 repeatyoyo

javascript 复制代码
<div class="box pink" id="loopBox"></div>

<script>

function runLoop() {
    if (tlLoop) tlLoop.kill();
    tlLoop = gsap.timeline({ repeat: -1, yoyo: true, repeatDelay: 0.3 });
    tlLoop.to("#loopBox", { x: 240, duration: 0.7 })
          .to("#loopBox", { rotation: 360, duration: 0.7 });
  }
</script>

四、控制与进阶

动画不只是「播放一次」

控制动画的播放状态

GSAP 的动画(包括前章的时间线)都会返回一个实例对象,调用它的方法即可操控:

方法 作用
.play() 从当前位置继续播放
.pause() 暂停
.reverse() 倒放(从当前位置往回)
.restart() 重头播放
.seek(t) 跳到时间 t(秒)处
.progress(p) 跳到进度 p(0~1)
.timeScale(s) 整体速度倍率,2 加速、0.5 慢放
.kill() 销毁动画、清除内联样式
javascript 复制代码
<div class="box" id="ctrlBox"></div>
<script>

const tween = gsap.to("#ctrlBox", { x: 300, rotation: 360, duration: 2, ease: "none", paused: true });

ctrlPlay.onclick    = () => tween.play();
ctrlPause.onclick   = () => tween.pause();
ctrlReverse.onclick = () => tween.reverse();
ctrlRestart.onclick = () => tween.restart();

</script>

监听生命周期回调

vars 里传入回调,可在动画的关键时刻执行代码:

回调 触发时机
onStart 动画开始第一次播放
onComplete 动画完整结束
onUpdate 每一帧更新(适合同步 UI)
onRepeat 每次重复时
javascript 复制代码
<div class="box blue" id="cbBox"></div>
<script>

  function runCb() {
    const log = (m) => (document.querySelector("#cbLog").textContent = m);
    if (cbTween) cbTween.kill();
    gsap.set("#cbBox", { x: 0 });
    cbTween = gsap.to("#cbBox", {
      x: 300, duration: 1.2,
      onStart:    () => log("▶ 动画开始"),
      onUpdate:   function () { log("帧: " + Math.round(this.progress() * 100) + "%"); },
      onComplete: () => log("✔ 完成")
    });
  }
</script>

实用案例 ①:加载进度条

javascript 复制代码
<div class="demo">
        <div style="background:var(--code-bg);border:1px solid var(--border);border-radius:10px;height:22px;overflow:hidden;margin-bottom:10px">
          <div id="bar" style="height:100%;width:0%;background:linear-gradient(90deg,var(--accent),#5fae00)"></div>
        </div>
        <div class="row" style="align-items:center">
          <button class="btn primary" onclick="runBar()">开始加载 ▶</button>
          <span id="barText" style="color:var(--text-dim);font-size:13px">0%</span>
        </div>
      </div>


<script>

  function runBar() {
    if (barTween) barTween.kill();
    gsap.set("#bar", { width: "0%" });
    document.querySelector("#barText").textContent = "0%";
    barTween = gsap.to("#bar", {
      width: "100%", duration: 2, ease: "power1.inOut",
      onUpdate: function () {
        const p = Math.round(this.progress() * 100);
        document.querySelector("#barText").textContent = p + "%";
      }
    });
  }
</script>

实用案例 ②:按钮悬停反馈

mouseenter / mouseleave 触发动画,配合 timeScale 让悬停时快速放大、离开时缓慢回弹。

javascript 复制代码
 <button class="btn primary" id="hoverBtn" style="font-size:16px;padding:14px 28px">悬停我</button>   

     const btn = document.querySelector("#hoverBtn");
    const hover = gsap.to(btn, { scale: 1.12, duration: 0.3, paused: true, ease: "power2.out" });
    btn.onmouseenter = () => hover.play();
    btn.onmouseleave = () => hover.reverse();

五、进阶插件 官方扩展

GSAP 核心之外,官方提供了一批插件来应对特定场景。

① ScrollTrigger --- 滚动到位置才触发

ScrollTrigger 让动画与页面滚动绑定:元素进入视口才播放,离开可反向。最典型的用途就是「滚动揭示(scroll reveal)」------内容随滚动逐块浮现。

javascript 复制代码
      <div class="reveal-wrap">
        <div class="reveal-card"><b>卡片 A</b> --- 进入视口时从下方淡入。</div>
        <div class="reveal-card"><b>卡片 B</b> --- 同样的 ScrollTrigger 配置。</div>
        <div class="reveal-card"><b>卡片 C</b> --- 滚动揭示非常适合长图文。</div>
        <div class="reveal-card"><b>卡片 D</b> --- 可配合 toggleActions 控制往返。</div>
        <div class="reveal-card"><b>卡片 E</b> --- 也可做进度条式滚动联动。</div>
      </div>

<script>

gsap.registerPlugin(ScrollTrigger);
  gsap.utils.toArray(".reveal-card").forEach((card) => {
    gsap.from(card, {
      y: 60, opacity: 0, duration: 0.8, ease: "power2.out",
      scrollTrigger: { trigger: card, start: "top 85%" }
    });
  });

</script>

② MotionPathPlugin --- 沿任意路径运动

让元素沿着一条 SVG 路径(曲线、圆形、任意形状)运动。只需把路径元素传给 motionPath.path,并用 align 让元素贴合路径。

javascript 复制代码
    <svg class="motion-svg" viewBox="0 0 400 150" preserveAspectRatio="none">
          <path id="track" d="M20,120 C70,10 150,10 200,75 S330,140 380,30" />
          <circle id="dot" r="9" />
    </svg>

<script>

gsap.registerPlugin(ScrollTrigger);

gsap.utils.toArray(".reveal-card").forEach((card) => {
  gsap.from(card, {
    y: 60, opacity: 0, duration: 0.8, ease: "power2.out",
    scrollTrigger: { trigger: card, start: "top 85%" } // 顶部到达视口 85% 处触发
  });
});
</script>

③ Flip --- 布局变化自动补间(FLIP 技术)

当你用 CSS/JS 改变了元素的位置或大小(如重新排序、切换网格/列表),Flip 会记录「前后状态」并自动生成平滑过渡,无需手写坐标。

javascript 复制代码
<div class="flip-grid" id="flipGrid">
          <div class="flip-item">1</div><div class="flip-item">2</div><div class="flip-item">3</div>
          <div class="flip-item">4</div><div class="flip-item">5</div><div class="flip-item">6</div>
          <div class="flip-item">7</div><div class="flip-item">8</div>
  </div>

<script>
gsap.registerPlugin(Flip);

function shuffleFlip() {
  const state = Flip.getState(".flip-item");   // 1) 记录当前布局
  // 2) 改变 DOM 顺序(真实重排)
  const grid = document.querySelector("#flipGrid");
  [...grid.children].sort(() => Math.random() - 0.5)
    .forEach(el => grid.appendChild(el));
  // 3) 让 Flip 自动补间到新布局
  Flip.from(state, { duration: 0.6, ease: "power2.out", stagger: 0.04 });
}
</script>

④ Draggable --- 让元素可拖拽并联动

Draggable 让元素支持鼠标/触摸拖拽,可限制方向或边界,并在拖动过程中回调,方便与其他动画联动

javascript 复制代码
<div class="drag-stage" id="dragStage">
          <div class="drag-box" id="dragBox">拖我</div>
        </div>
<script>

gsap.registerPlugin(Draggable);

Draggable.create("#dragBox", {
  type: "x,y",               // 允许 xy 自由拖动
  bounds: "#dragStage",       // 限制在容器内
  onDrag: function() {       // 拖动时实时联动
    dragInfo.textContent = `x:${Math.round(this.x)}  y:${Math.round(this.y)}`;
  }
});
</script>

⑤ TextPlugin --- 逐字「打字机」效果

TextPlugin 让元素的文字内容参与补间,从而做出逐字出现/替换的打字机效果。

javascript 复制代码
  <div class="type-text" id="typeText"></div>

<script>

gsap.registerPlugin(TextPlugin);

gsap.to("#typeText", {
  text: "你好,我是用 GSAP TextPlugin 逐字打出来的文字。",
  duration: 2.2,
  ease: "none"            // 匀速逐字出现
});
</script>
相关推荐
Bernice橘子4 小时前
职场英语学习计划Day034
学习
磊灬泽5 小时前
【从零学习 MQTT】发布/订阅、主题、QoS 与报文解析
学习
0566465 小时前
Python数据结构——循环队列
python·学习
天国梦5 小时前
2026高中生英语词汇学习APP测评:天学网等4款产品实测对比
学习
我爱cope6 小时前
【计算机网络 | 物理层3:数字编码与调制:比特如何变成可传输的信号?】
网络·学习·计算机网络
一只小菜鸡..6 小时前
南京大学 操作系统 (JYY) 学习笔记:最终章——操作系统的宇宙,与我们的星辰大海
笔记·学习
0566469 小时前
Python高级——迭代器
开发语言·python·学习
math_hongfan9 小时前
鸿蒙Agent高级技能自定义开发:自定义意图服务/能力注册/Agent技能编排/服务插件开发实战
android·学习·华为·harmonyos·鸿蒙
math_hongfan9 小时前
鸿蒙AI权限与隐私保护高级:智能数据脱敏/端侧处理优先/数据最小化采集/隐私计算技术栈
人工智能·学习·华为·harmonyos·鸿蒙
duhong202610 小时前
Linux刷题记录第一套
学习