普通视图

发现新文章,点击刷新页面。
今天 — 2026年2月14日首页

gsap 配置解读 --3

作者 大时光
2026年2月14日 10:14

drawSVG 是什么

  <div class="card">
    <h1>案例 15:DrawSVG 绘制路径</h1>
    <p>DrawSVGPlugin 可以控制路径的绘制百分比。</p>
    <svg viewBox="0 0 200 200">
      <path id="path" class="stroke" d="M40 100 C40 40, 160 40, 160 100 C160 160, 40 160, 40 100" />
    </svg>
    <button id="play">绘制路径</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/DrawSVGPlugin.min.js"></script>
  <script>
    const path = document.querySelector("#path");
    const playButton = document.querySelector("#play");

    // 注册 DrawSVGPlugin
    gsap.registerPlugin(DrawSVGPlugin);

    // drawSVG: "0% 100%" 表示从头绘制到尾
    const tween = gsap.fromTo(
      path,
      { drawSVG: "0% 0%" },
      { drawSVG: "0% 100%", duration: 1.6, ease: "power2.out", paused: true }
    );

    playButton.addEventListener("click", () => {
      tween.restart();
    });
  </script>

drawSVGGSAP(GreenSock Animation Platform)官方提供的一个强大插件 —— DrawSVGPlugin 的核心功能,专门用于以动画方式“绘制”或“擦除” SVG 路径(<path><line><polyline><polygon><rect><circle> 等),实现类似“手绘”、“描边动画”的效果。


📌 你的代码解释:

gsap.fromTo(
  path,
  { drawSVG: "0% 0%" },      // 起始状态:路径完全未绘制(0% 到 0%)
  { drawSVG: "0% 100%", duration: 1.6, ease: "power2.out", paused: true }
);

这段代码的作用是:

让 SVG 路径从“完全隐藏”状态,平滑地“画出来”,直到完整显示整个路径。

点击按钮后,调用 tween.restart() 重新播放这个绘制动画。


drawSVG 的工作原理

SVG 路径本身是一条“线”,但默认是立即完整显示的。
DrawSVGPlugin 通过动态控制 SVG 的 stroke-dasharraystroke-dashoffset 属性,来只显示路径的一部分,从而模拟“绘制”过程。

  • drawSVG: "0% 0%" → 显示 0% 到 0% → 完全隐藏
  • drawSVG: "0% 50%" → 显示前 50%
  • drawSVG: "0% 100%" → 显示全部 → 完整路径
  • drawSVG: "100% 100%" → 也完全隐藏(可以用来做“擦除”效果)

💡 它支持百分比("0% 100%")、绝对长度("0px 200px")或关键词("start", "end")。


🔧 常见用法示例

1. 从头到尾绘制(你的例子)
{ drawSVG: "0% 100%" }
2. 从尾到头绘制(反向)
{ drawSVG: "100% 0%" } // 注意顺序:起始 > 结束 = 反向
3. 中间一段高亮(常用于进度指示)
{ drawSVG: "40% 60%" }
4. 擦除效果(从完整到消失)
gsap.to(path, { drawSVG: "0% 0%", duration: 1 });
5. 循环绘制 + 擦除
gsap.to(path, {
  drawSVG: "0% 100%",
  duration: 1,
  yoyo: true,
  repeat: -1
});

✅ 支持的 SVG 元素

元素 是否支持
<path> ✅ 最常用
<line>
<polyline>
<polygon>
<rect> ✅(需有 stroke
<circle> / <ellipse>
<text> ❌(不支持,但可用 textPath 包裹路径)

⚠️ 要求元素必须有 stroke(描边),且 stroke-width > 0。填充(fill)不影响绘制动画。


🎨 样式建议(CSS)

.stroke {
  fill: none;           /* 通常设为无填充 */
  stroke: #3b82f6;      /* 描边颜色 */
  stroke-width: 4;      /* 描边宽度 */
  stroke-linecap: round;/* 线帽样式(可选)*/
}

⚠️ 注意事项

  1. 必须注册插件

    gsap.registerPlugin(DrawSVGPlugin);
    
  2. 路径必须是“单一线条”
    复杂组合路径(如多个子路径)可能表现异常,建议简化或拆分。

  3. 性能优秀
    DrawSVGPlugin 内部优化良好,即使在低端设备上也能流畅运行。

  4. 与 ScrollTrigger 结合极佳
    常用于“滚动触发动画”:

    gsap.to(path, {
      scrollTrigger: ".section",
      drawSVG: "0% 100%",
      duration: 1
    });
    

✅ 总结

术语 含义
drawSVG GSAP 的 DrawSVGPlugin 提供的属性,用于控制 SVG 路径的“绘制进度”
典型值 "0% 0%"(隐藏)、"0% 100%"(完整绘制)、"100% 0%"(反向绘制)

EaselPlugin是什么

<div class="card">
    <h1>案例 16:EaselPlugin + Canvas</h1>
    <p>用 GSAP 驱动 EaselJS 的对象属性。</p>
    <canvas id="stage" width="420" height="220"></canvas>
    <button id="play">播放动画</button>
  </div>
  <script src="https://code.createjs.com/1.0.0/easeljs.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/EaselPlugin.min.js"></script>
  <script>
    const canvas = document.querySelector("#stage");
    const playButton = document.querySelector("#play");

    // 创建 EaselJS 舞台与图形
    const stage = new createjs.Stage(canvas);
    const circle = new createjs.Shape();
    circle.graphics.beginFill("#38bdf8").drawCircle(0, 0, 26);
    circle.x = 60;
    circle.y = 110;
    stage.addChild(circle);
    stage.update();

    // 注册 EaselPlugin
    gsap.registerPlugin(EaselPlugin);

    // GSAP 让 EaselJS 图形移动与缩放
    const tween = gsap.to(circle, {
      x: 360,
      scaleX: 1.4,
      scaleY: 1.4,
      duration: 1.4,
      ease: "power2.out",
      paused: true
    });

    // 每帧刷新舞台
    gsap.ticker.add(() => {
      stage.update();
    });

    playButton.addEventListener("click", () => {
      tween.restart();
    });
  </script>

EaselJSCreateJS 套件中的一个核心库,专门用于在 HTML5 <canvas> 画布上进行高性能的 2D 图形绘制与交互开发。它提供了一套类似 Flash/ActionScript 的面向对象 API,让开发者能轻松创建、操作和动画化矢量图形、位图、文本等元素。


📌 在你的代码中,EaselJS 的作用是:

  1. 创建一个 Canvas 舞台(Stage)
  2. 绘制一个圆形(Shape)并添加到舞台上
  3. 通过 GSAP + EaselPlugin 控制该圆形的位置和缩放

EaselPlugin 是 GSAP 的一个官方插件,让 GSAP 能直接动画化 EaselJS 对象的属性(如 x, y, scaleX, rotation 等),并自动触发舞台重绘。


✅ EaselJS 核心概念

概念 说明
Stage 代表整个 <canvas> 画布,是所有显示对象的容器
DisplayObject 所有可视对象的基类(如 Shape, Bitmap, Text, Container
Shape 用于绘制矢量图形(圆、矩形、路径等)
Ticker EaselJS 自带的帧循环(但你的代码用的是 GSAP 的 ticker 来更新舞台)

🔍 你的代码逐行解析

// 1. 创建 EaselJS 舞台
const stage = new createjs.Stage(canvas);

// 2. 创建一个圆形 Shape
const circle = new createjs.Shape();
circle.graphics.beginFill("#38bdf8").drawCircle(0, 0, 26); // 画一个半径26的圆
circle.x = 60;
circle.y = 110;

// 3. 将圆形添加到舞台
stage.addChild(circle);

// 4. 首次渲染(否则看不到)
stage.update();
// 5. 注册 GSAP 插件
gsap.registerPlugin(EaselPlugin);

// 6. 用 GSAP 动画化 EaselJS 对象!
const tween = gsap.to(circle, {
  x: 360,       // EaselJS 对象的 x 属性
  scaleX: 1.4,  // 缩放
  scaleY: 1.4,
  duration: 1.4,
  ease: "power2.out",
  paused: true
});
// 7. 关键:每帧刷新 Canvas!
gsap.ticker.add(() => {
  stage.update(); // 告诉 EaselJS 重新绘制整个舞台
});

💡 如果没有 stage.update(),Canvas 不会更新,动画就“看不见”!


✅ 为什么需要 EaselPlugin

  • EaselJS 对象的属性(如 x, scaleX不是直接作用于 DOM 或 CSS,而是存储在 JavaScript 对象中。
  • GSAP 默认不知道如何“读取/写入”这些属性,也不知道何时需要调用 stage.update()
  • EaselPlugin 桥接了 GSAP 和 EaselJS
    • 自动识别 createjs.DisplayObject
    • 正确设置/获取 x, y, rotation, scaleX/Y, alpha 等属性
    • (可选)自动调用 stage.update()(但你的代码手动用 gsap.ticker 控制,更灵活)

🎯 EaselJS 的典型应用场景

场景 说明
游戏开发 2D 小游戏(平台跳跃、射击、解谜等)
数据可视化 动态图表、交互式信息图
广告 Banner HTML5 富媒体广告(替代 Flash)
教育/演示动画 复杂交互动画、流程演示
Canvas UI 组件 自定义控件、非 DOM 的界面

⚠️ 注意事项

  1. 性能 vs DOM
    Canvas 适合大量图形或高频更新(如游戏),但不支持 SEO、无障碍访问(a11y)。简单 UI 优先用 DOM + CSS。

  2. 坐标系
    EaselJS 使用标准 Canvas 坐标系:左上角 (0,0),向右为 X+,向下为 Y+。

  3. 事件处理
    EaselJS 支持鼠标/触摸事件(circle.on("click", handler)),但需启用:

    stage.enableMouseOver(10); // 启用 hover
    
  4. 替代方案
    现代项目也可考虑:

    • 纯 Canvas + requestAnimationFrame
    • PixiJS(更强大,支持 WebGL)
    • Three.js(3D)
    • SVG + GSAP(矢量、可访问性好)

✅ 总结

术语 含义
EaselJS 一个基于 HTML5 Canvas 的 2D 图形库,提供类似 Flash 的开发体验
EaselPlugin GSAP 插件,让 GSAP 能无缝动画化 EaselJS 对象的属性

你的代码展示了 “用 GSAP 驱动 Canvas 图形动画” 的经典模式:

  • EaselJS 负责 图形创建与渲染
  • GSAP 负责 复杂缓动、时间控制、序列编排
  • gsap.ticker 负责 每帧刷新画面

这种组合在需要精细控制 Canvas 动画时非常高效!

Flip 是什么

<div class="card">
    <h1>案例 17:Flip 位置变换</h1>
    <p>Flip 能把布局切换变成平滑动画。</p>
    <div class="grid" id="grid">
      <div class="item highlight">A</div>
      <div class="item">B</div>
      <div class="item">C</div>
      <div class="item">D</div>
      <div class="item">E</div>
      <div class="item">F</div>
    </div>
    <button id="toggle">切换布局</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/Flip.min.js"></script>
  <script>
    const grid = document.querySelector("#grid");
    const toggleButton = document.querySelector("#toggle");
    let expanded = false;

    // 注册 Flip 插件
    gsap.registerPlugin(Flip);

    toggleButton.addEventListener("click", () => {
      const items = gsap.utils.toArray(".item");

      // 记录布局状态
      const state = Flip.getState(items);

      // 切换布局
      expanded = !expanded;
      grid.style.gridTemplateColumns = expanded ? "repeat(2, 1fr)" : "repeat(3, 1fr)";
      items[0].classList.toggle("highlight", expanded);
      items[0].style.gridColumn = expanded ? "span 2" : "auto";

      // 用 Flip 生成补间动画
      Flip.from(state, {
        duration: 0.8,
        ease: "power2.inOut",
        stagger: 0.04
      });
    });
  </script>

FlipGSAP(GreenSock Animation Platform)官方提供的一个革命性插件 —— FlipPlugin,它的名字是 "First, Last, Invert, Play" 的缩写,是一种高效实现布局变换平滑动画的技术


🎯 核心思想:“记录变化前后的状态,自动生成中间过渡动画”

你不需要手动计算元素移动了多少像素、缩放了多少倍——
只需改变 DOM 结构或 CSS 布局(如 grid、flex、class、style),Flip 会自动检测差异并补间!


📌 你的代码解释:

// 1. 记录当前所有 .item 元素的状态(位置、尺寸等)
const state = Flip.getState(items);

// 2. 改变布局(这是“瞬间”的,没有动画)
expanded = !expanded;
grid.style.gridTemplateColumns = expanded ? "repeat(2, 1fr)" : "repeat(3, 1fr)";
items[0].classList.toggle("highlight", expanded);
items[0].style.gridColumn = expanded ? "span 2" : "auto";

// 3. 让 Flip 从“旧状态”动画到“新状态”
Flip.from(state, {
  duration: 0.8,
  ease: "power2.inOut",
  stagger: 0.04
});

效果:点击按钮后,网格从 3 列变为 2 列,第一个 item 跨两列并高亮,其他元素平滑地移动、缩放到新位置,而不是“跳变”。


🔍 Flip 的工作原理(F.L.I.P.)

步骤 含义 你的代码中
F - First 记录元素变化前的位置/尺寸 Flip.getState(items)
L - Last 应用新的布局(DOM/CSS 改变) 修改 gridTemplateColumnsgridColumn
I - Invert 通过 transform 将元素视觉上“倒回”到原始位置(用户看不见这一步) Flip 内部自动完成
P - Play 动画 transform 回到新位置,形成平滑过渡 Flip.from(state, {...})

💡 这种技术避免了强制重排(reflow),性能极高!


✅ Flip 的核心优势

优势 说明
零计算 无需手动算 x, y, width, height
自动处理复杂布局 支持 Grid、Flexbox、绝对定位、浮动等
高性能 只使用 transformopacity,60fps 流畅
智能匹配元素 自动根据 DOM 节点或 key 属性关联前后元素
支持嵌套、增删元素 可配合 onEnter, onLeave 处理新增/移除项

🔧 常见用法扩展

1. 指定唯一 key(推荐用于动态列表)
// 给每个 item 加 data-id
<div class="item" data-flip-id="A">A</div>

// Flip 会按 data-flip-id 匹配元素
Flip.from(state, { 
  absolute: true, // 使用绝对定位避免布局抖动
  simple: true    // 简化动画(仅位移+缩放)
});
2. 处理新增/删除元素
Flip.from(state, {
  onEnter: (elements) => gsap.from(elements, { opacity: 0, scale: 0 }), // 新增项淡入
  onLeave: (elements) => gsap.to(elements, { opacity: 0 })              // 移除项淡出
});
3. 与 React/Vue 集成

在虚拟 DOM 更新后调用 Flip.getState() → 触发渲染 → 调用 Flip.from(),实现声明式布局动画。


⚠️ 注意事项

  • 必须注册插件
    gsap.registerPlugin(Flip);
    
  • 元素需有明确尺寸和位置(避免 display: none 或未渲染状态)
  • 默认使用相对定位,若布局跳动可加 absolute: true
  • 不适用于纯颜色/文本内容变化(那是 CSS Transition 的领域)

✅ 总结

术语 含义
Flip (FlipPlugin) GSAP 插件,通过记录布局前后状态,自动生成平滑的元素位置/尺寸变换动画

你的代码是一个典型的 “响应式网格布局切换” 示例,广泛应用于:

  • 卡片列表 ↔ 网格视图切换
  • 侧边栏展开/收起
  • 动态表单布局调整
  • 数据可视化重排

💡 一句话记住 Flip
“改 CSS,记状态,自动生成动画” —— 布局动画从未如此简单!

什么是GSDevTools

 <div class="card">
      <h1>案例 18:GSDevTools 调试面板</h1>
      <p>GSDevTools 用来调试时间线与动画进度。</p>
      <div class="stage">
        <div class="block" id="block"></div>
      </div>
      <div class="hint">页面底部会出现调试面板</div>
    </div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/GSDevTools.min.js"></script>
    <script>
      const block = document.querySelector("#block");

      // 创建一个循环时间线
      const timeline = gsap.timeline({ repeat: -1, yoyo: true });
      timeline.to(block, { x: 460, duration: 1.4, ease: "power2.inOut" });
      timeline.to(block, { rotation: 180, duration: 0.8, ease: "power2.inOut" }, 0);

      // 创建调试面板
      GSDevTools.create({ animation: timeline });
    </script>

image.png

什么是 InertiaPlugin

<div class="card">
    <h1>案例 19:Inertia 惯性拖拽</h1>
    <p>松手后带惯性滑动。</p>
    <div class="stage">
      <div class="ball" id="ball"></div>
    </div>
    <div class="hint">拖动小球后快速松手</div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/Draggable.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/InertiaPlugin.min.js"></script>
  <script>
    const ball = document.querySelector("#ball");

    // 注册插件
    gsap.registerPlugin(Draggable, InertiaPlugin);

    // 开启惯性效果
    Draggable.create(ball, {
      type: "x,y",
      bounds: ".stage",
      inertia: true
    });
  </script>

就是添加这个属性 是否开启惯性 inertia: true

MotionPathPlugin是什么

<div class="card">
      <h1>案例 20:MotionPath 路径运动</h1>
      <p>让元素沿着 SVG 路径运动。</p>
      <svg viewBox="0 0 420 220">
        <path
          id="track"
          class="path"
          d="M20 180 C120 40, 300 40, 400 180"
        />
        <circle id="dot" class="dot" r="10" cx="20" cy="180"></circle>
      </svg>
      <button id="play">沿路径运动</button>
    </div>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/MotionPathHelper.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/MotionPathPlugin.min.js"></script>
    <script>
      const dot = document.querySelector("#dot");
      const track = document.querySelector("#track");
      const playButton = document.querySelector("#play");

      // 注册 MotionPathPlugin
      gsap.registerPlugin(MotionPathPlugin);

      const tween = gsap.to(dot, {
        duration: 1.8,
        ease: "power1.inOut",
        motionPath: {
          path: track,
          align: track,
          alignOrigin: [0.5, 0.5]
        },
        paused: true
      });

      playButton.addEventListener("click", () => {
        tween.restart();
      });
    </script>

motionPathGSAP(GreenSock Animation Platform) 动画库中的一个强大功能,由 MotionPathPlugin 插件提供,用于让元素沿着指定的 路径(path) 进行动画运动。


📌 简单定义:

motionPath 允许你将一个 DOM 元素(如 <div><circle> 等)沿着 SVG 路径(<path><circle><rect> 等)或一组坐标点进行平滑移动,并可自动旋转以对齐路径方向。


✅ 核心特性:

  1. 路径支持多种格式

    • SVG 的 <path> 元素(最常用)
    • 其他 SVG 形状(如 <circle>, <rect>, <polygon>
    • 一组 {x, y} 坐标点组成的数组
    • 字符串形式的 SVG 路径数据(d 属性)
  2. 自动对齐(align)

    • 可通过 align: path 让元素在移动时朝向路径切线方向(比如让飞机头始终指向飞行方向)。
    • alignOrigin 控制对齐的“锚点”,例如 [0.5, 0.5] 表示元素中心对齐。
  3. 精确控制

    • 支持 startend 属性,控制沿路径的起止位置(0 到 1)。
    • 可结合 GSAP 的时间轴、缓动函数(ease)、重复等高级功能。

gsap.to(dot, {
  duration: 1.8,
  ease: "power1.inOut",
  motionPath: {
    path: track,           // 沿着 #track 这个 SVG 路径移动
    align: track,          // 元素方向对齐路径
    alignOrigin: [0.5, 0.5] // 以圆点中心为对齐基准
  },
  paused: true
});
  • #dot(一个小圆)会从路径起点 (20,180) 开始,
  • 沿着贝塞尔曲线 M20 180 C120 40, 300 40, 400 180 移动到终点 (400,180)
  • 移动过程中,由于设置了 align,它会自动旋转以匹配路径的走向(虽然圆形看不出旋转,但如果是箭头就很明显)。

💡 注:圆形 (<circle>) 本身没有方向感,所以 align 效果不明显。若换成 <use> 引用一个飞机图标,就能看到“朝向路径”的效果。


🌟 应用场景:

  • 游戏角色沿轨道移动
  • 数据可视化中的动态轨迹
  • 引导式 UI 动画(如教程提示沿路径走)
  • 创意交互动画(如文字沿曲线飞入)

📚 官方文档:

👉 greensock.com/docs/v3/Plu…


总结:motionPath 是 GSAP 中实现“路径动画”的核心工具,让复杂轨迹运动变得简单、流畅且高度可控。

昨天 — 2026年2月13日首页

gsap 配置解读 --2

作者 大时光
2026年2月13日 15:22

yoyo 是什么意思

在 GSAP(GreenSock Animation Platform)中,yoyo: true 是一个控制重复动画播放方向的选项

const tween = gsap.to(slider, {
x: 420,
duration: 1.2, 
ease: "power1.inOut",
repeat: -1, // 无限重复
yoyo: true, // ← 关键:开启“来回”模式
paused: true
});

这段代码的作用是:

让 slider 元素在 x: 0 和 x: 420 之间无限来回移动(像钟摆一样),每次往返耗时 2.4 秒(1.2 秒去 + 1.2 秒回)。


✅ yoyo: true 的核心行为

yoyo 动画重复时的行为
false(默认) 每次重复都从头开始0 → 420,然后重置回 0 再 0 → 420(会有“跳回”感)
true 每次重复都反向播放0 → 420,然后 420 → 0,再 0 → 420……形成平滑来回
对比示例:
  • repeat: -1, yoyo: false
    0 → 420 → 瞬间跳回 0 → 0 → 420 → 瞬间跳回 0 …(不连贯)
  • repeat: -1, yoyo: true
    0 → 420 → 420 → 0 → 0 → 420 → 420 → 0 …(流畅往复)

💡 yoyo 这个名字来源于“悠悠球”——扔出去再自动收回来,形象地表达了“来回”运动。


🔧 配合 repeat 使用

  • repeat: 1 + yoyo: true → 播放一次正向 + 一次反向(共 2 次)
  • repeat: -1 + yoyo: true → 无限循环往复(最常见用法)
  • repeat: 0(默认)→ yoyo 无效(因为没有重复)

🎯 常见应用场景

  1. 背景元素左右/上下浮动

    js

    gsap.to(".cloud", { x: 100, repeat: -1, yoyo: true, duration: 3 });
    
  2. 指示器、光标闪烁或晃动

    js

    gsap.to(".cursor", { opacity: 0, repeat: -1, yoyo: true, duration: 0.5 });
    
  3. 机械式往复运动(如风扇叶片微调、机器人手臂)


⚠️ 注意事项

  • yoyo 只影响动画的播放方向,不会改变 ease(缓动)。

    • 正向:使用你指定的 ease(如 "power1.inOut"
    • 反向:GSAP 会自动反转缓动曲线,确保运动自然(无需手动设置)
  • 如果你用了 keyframesyoyo 会反转整个关键帧序列。


✅ 总结

配置 含义
repeat: -1 无限重复动画
yoyo: true 每次重复时反向播放,实现“来回”效果

你的代码创建了一个水平方向无限来回滑动的动画,常用于:

  • 轮播图自动滚动(配合暂停/继续)
  • 装饰性动态元素
  • 游戏中的巡逻敌人/NPC

配合 paused: true,你可以在需要时(如鼠标悬停、点击按钮)通过 tween.play() 启动这个循环动画。

onStart onUpdate onComplete 是什么意思

在 GSAP(GreenSock Animation Platform)中,onStartonUpdate 和 onComplete 是 动画生命周期回调函数(callback functions) ,用于在动画的特定时刻执行自定义 JavaScript 代码

 const tween = gsap.to(dot, {
        x: 460,
        duration: 1.4,
        ease: "power2.out",
        paused: true,
        onStart: () => {
          log.textContent = "动画开始...";
        },
        onUpdate: () => {
          const progress = Math.round(tween.progress() * 100);
          log.textContent = `进行中:${progress}%`;
        },
        onComplete: () => {
          log.textContent = "动画完成!";
        }
      });

这段代码为动画定义了三个关键时机的“监听器”:


✅ 各回调函数的作用

回调 触发时机 常见用途
onStart 动画刚开始播放的第一帧(在第一次渲染前) 显示提示、启动计时器、添加 class 等
onUpdate 每一帧动画更新时都会触发(每秒约 60 次) 实时更新进度条、显示百分比、同步其他元素状态
onComplete 动画完全结束(到达最后一帧) 隐藏元素、跳转页面、播放音效、触发下一个动画

🔍 详细说明

1. onStart
  • 只会执行 一次
  • 在动画真正开始移动/变化之前触发。
  • 适合做“初始化”操作。

✅ 示例:

js

onStart: () => {
  dot.classList.add('animating');
  console.log('Dot animation started!');
}

2. onUpdate
  • 高频触发(每帧一次),性能敏感,避免做 heavy 操作(如 DOM 查询、复杂计算)。
  • 常配合 tween.progress()(返回 0~1 的进度值)或 tween.time() 使用。

✅ 你的代码:

js

onUpdate: () => {
  const progress = Math.round(tween.progress() * 100); // 转为 0~100%
  log.textContent = `进行中:${progress}%`;
}

→ 实时显示动画完成百分比。

💡 提示:如果只是想读取当前属性值,也可以用 gsap.getProperty(dot, "x")


3. onComplete
  • 动画正常播放完毕时触发(不包括被暂停、反向或 killed 的情况)。
  • 如果设置了 repeat: -1onComplete 永远不会触发(因为动画永不结束)。

✅ 示例:

js

onComplete: () => {
  setTimeout(() => dot.style.display = 'none', 500);
  playNextAnimation();
}

⚠️ 其他相关回调(扩展)

回调 说明
onReverseComplete 反向播放完成时触发(比如调用了 tween.reverse() 并回到起点)
onRepeat 每次重复开始时触发(需配合 repeat 使用)
onInterrupt 动画被kill 或 stop 时触发(GSAP 3.10+)

✅ 总结

回调 何时运行 你的代码作用
onStart 动画刚开始 显示 “动画开始...”
onUpdate 每一帧更新 实时显示进度百分比
onComplete 动画彻底结束 显示 “动画完成!”

这些回调让你能精确控制动画与 UI、逻辑、数据的同步,是实现高级交互动效的关键工具。

💡 小技巧:即使 paused: true,一旦你调用 tween.play(),这些回调仍会按规则触发。

tween.play tween.pause tween.reverse tween.restart是什么意思

在 GSAP(GreenSock Animation Platform)中,tween.play()tween.pause()tween.reverse() 和 tween.restart() 是 控制动画播放状态的核心方法。它们让你可以像操作视频播放器一样,灵活地控制动画的播放、暂停、倒放和重播。

 const ship = document.querySelector("#ship");
      const progress = document.querySelector("#progress");
      const playButton = document.querySelector("#play");
      const pauseButton = document.querySelector("#pause");
      const reverseButton = document.querySelector("#reverse");
      const restartButton = document.querySelector("#restart");

      // 创建一个补间并绑定更新进度条
      const tween = gsap.to(ship, {
        x: 470,
        duration: 3,
        ease: "power1.inOut",
        paused: true,
        onUpdate: () => {
          progress.value = Math.round(tween.progress() * 100);
        }
      });

      playButton.addEventListener("click", () => tween.play());
      pauseButton.addEventListener("click", () => tween.pause());
      reverseButton.addEventListener("click", () => tween.reverse());
      restartButton.addEventListener("click", () => tween.restart());

      // 拖动进度条,手动 seek 到指定位置
      progress.addEventListener("input", (event) => {
        const value = Number(event.target.value) / 100;
        tween.progress(value).pause();
      });

假设你有如下动画:

js

const tween = gsap.to(box, {
  x: 300,
  duration: 2,
  paused: true // 初始暂停,等待手动控制
});

此时动画已创建但未播放。你可以通过以下方法控制它:


✅ 1. tween.play()

作用:从当前进度开始正向播放动画。

  • 如果是第一次播放 → 从头开始(进度 0 → 1)
  • 如果之前被暂停在 50% → 从 50% 继续播放到 100%

js

tween.play(); // 开始或继续播放

💡 相当于点击“播放”按钮 ▶️


✅ 2. tween.pause()

作用暂停动画,停留在当前帧。

  • 动画状态被冻结,不会继续更新。
  • 可随时用 play() 或 reverse() 恢复。

js

tween.pause(); // 暂停动画
console.log(tween.progress()); // 比如输出 0.6(60% 进度)

💡 相当于点击“暂停”按钮 ⏸️


✅ 3. tween.reverse()

作用反向播放动画(倒放)。

  • 如果当前在正向播放 → 立即掉头往回走
  • 如果已暂停 → 从当前位置倒放到起点
  • 再次调用 reverse() 会切回正向

js

tween.reverse(); // 开始倒放
// 再次调用:
tween.reverse(); // 又变回正向播放

💡 相当于“倒带” ◀️,常用于 hover 离开时还原状态


✅ 4. tween.restart()

作用重置并重新播放动画(从头开始)。

  • 无论当前在什么进度,都会跳回 0%  并开始正向播放。
  • 相当于 tween.progress(0).play()

js

tween.restart(); // 从头开始播放

💡 相当于“重新开始” 🔁


🔄 状态变化图示

假设动画总时长 2 秒:

方法 当前进度 调用后行为
初始 0%
.play() 0% → 正向播放 → 100%
播放到 60% 时 .pause() 停在 60%
.play() 60% → 继续正向 → 100%
.reverse() 60% → 倒放 → 0%
.restart() 无论在哪 → 跳回 0% → 正向播放

💡 实际应用场景

场景 1:Hover 效果

js

box.addEventListener('mouseenter', () => tween.play());
box.addEventListener('mouseleave', () => tween.reverse());
场景 2:按钮控制

js

playBtn.onclick = () => tween.play();
pauseBtn.onclick = () => tween.pause();
resetBtn.onclick = () => tween.restart();
场景 3:滚动触发动画

js

ScrollTrigger.create({
  trigger: ".section",
  onEnter: () => tween.play(),
  onLeaveBack: () => tween.reverse()
});

⚠️ 注意事项

  • 这些方法返回 tween 自身,支持链式调用:

    js

    tween.play().timeScale(2); // 2倍速播放
    
  • reverse() 不会改变 duration,只是反向运行。

  • 如果动画已完成(100%),调用 play() 不会重播(需用 restart())。


✅ 总结

方法 作用 类比
.play() 从当前位置正向播放 ▶️ 播放
.pause() 暂停在当前帧 ⏸️ 暂停
.reverse() 从当前位置反向播放 ◀️ 倒放
.restart() 重置到开头并播放 🔁 重播

这些方法赋予你对 GSAP 动画完全的程序化控制能力,是实现交互动效的基础。

gsap.defaults 是什么

在 GSAP(GreenSock Animation Platform)中,gsap.defaults()  是一个全局配置方法,用于为所有后续创建的 GSAP 动画(tween 或 timeline)设置默认参数,避免重复书写相同的配置项(如 durationease 等)。

   const boxes = gsap.utils.toArray(".box");
      const playButton = document.querySelector("#play");

      // 设置默认动画参数
      gsap.defaults({
        duration: 0.8,
        ease: "power2.out"
      });

      const timeline = gsap.timeline({ paused: true });

      timeline.to(boxes[0], { x: 220, background: "#22d3ee" });
      timeline.to(boxes[1], { x: 180, background: "#a3e635" }, "<0.1");
      timeline.to(boxes[2], { x: 140, background: "#f472b6" }, "<0.1");

      playButton.addEventListener("click", () => {
        timeline.restart();
      });

这行代码的意思是:

从此以后,所有通过 gsap.to()gsap.from()gsap.timeline().to() 等创建的动画,如果没有显式指定 duration 和 ease,就会自动使用 duration: 0.8 和 ease: "power2.out"


✅ 作用:减少重复代码,统一动效风格

在你的后续代码中:

js

timeline.to(boxes[0], { x: 220, background: "#22d3ee" });
timeline.to(boxes[1], { x: 180, background: "#a3e635" }, "<0.1");
timeline.to(boxes[2], { x: 140, background: "#f472b6" }, "<0.1");

虽然你没有写 duration 和 ease,但由于前面设置了 gsap.defaults(),这三个 .to() 动画会自动继承

  • duration: 0.8
  • ease: "power2.out"

等价于:

js

timeline.to(boxes[0], { x: 220, background: "#22d3ee", duration: 0.8, ease: "power2.out" });
// ...其他同理

🔧 gsap.defaults() 支持的常用属性

属性 说明
duration 默认动画时长(秒)
ease 默认缓动函数(如 "power2.out""elastic""back.inOut" 等)
delay 默认延迟时间
overwrite 默认覆盖行为(如 "auto"
opacity 默认透明度(较少用)

⚠️ 注意:局部配置会覆盖默认值
例如:gsap.to(el, { x: 100, duration: 2 }) 中的 duration: 2 会覆盖 defaults 中的 0.8


🎯 使用场景

  1. 项目级动效规范
    整个网站/应用使用统一的动画节奏和缓动曲线。
  2. 快速原型开发
    先用默认值快速搭建动画,后期再微调个别参数。
  3. 减少样板代码
    避免在几十个动画中反复写 duration: 0.8, ease: "power2.out"

⚠️ 注意事项

  • gsap.defaults() 只影响调用之后创建的动画,对已存在的 tween/timeline 无效。
  • 它设置的是全局默认值,会影响所有 GSAP 动画(包括 gsap.totimeline.to 等)。
  • 如果你在团队协作中使用,建议在项目入口文件(如 main.js)中统一设置。

gsap.quickTo 和 gsap.utils.clamp 是什么

GSAP 的两个非常高效且实用的工具:gsap.quickTo()  和 gsap.utils.clamp() 。它们常用于高性能指针/光标跟随、拖拽、实时交互等场景。下面分别详细解释:


  const stage = document.querySelector("#stage");
      const cursor = document.querySelector("#cursor");

      // quickTo 可以高频率更新属性,且保持平滑
      const moveX = gsap.quickTo(cursor, "x", { duration: 0.3, ease: "power3.out" });
      const moveY = gsap.quickTo(cursor, "y", { duration: 0.3, ease: "power3.out" });

      // utils.clamp 限制数值范围
      const clampX = gsap.utils.clamp(0, stage.clientWidth - 36);
      const clampY = gsap.utils.clamp(0, stage.clientHeight - 36);

      stage.addEventListener("mousemove", (event) => {
        const rect = stage.getBoundingClientRect();
        const x = clampX(event.clientX - rect.left - 18);
        const y = clampY(event.clientY - rect.top - 18);
        moveX(x);
        moveY(y);
      });

✅ 1. gsap.quickTo()

🔍 是什么?

gsap.quickTo() 是 GSAP 提供的一个高性能属性更新器,它会预先创建一个轻量级的 tween(动画) ,然后你可以通过调用返回的函数高频次地更新目标值,而无需反复创建新动画。

📌 你的代码:

js

const moveX = gsap.quickTo(cursor, "x", { duration: 0.3, ease: "power3.out" });
const moveY = gsap.quickTo(cursor, "y", { duration: 0.3, ease: "power3.out" });
  • 创建了两个“快速更新器”:moveX 和 moveY
  • 它们分别控制 cursor 元素的 x 和 y 属性
  • 每次调用 moveX(100),就会让 cursor 的 x 平滑地动画到 100(耗时 0.3 秒,带缓动)

🎯 在事件中使用:

js

stage.addEventListener("mousemove", (event) => {
  // ...计算 x, y
  moveX(x); // ← 高频调用(每秒可能几十次)
  moveY(y);
});

✅ 为什么用 quickTo 而不用 gsap.to

表格

方式 问题
gsap.to(cursor, { x: newX, duration: 0.3 }) 每次 mousemove 都新建一个 tween,内存和性能开销大,容易卡顿
gsap.quickTo(...) 只创建一次 tween,后续只是更新它的目标值,极其高效 ✅

💡 quickTo 内部会自动处理“中断上一帧动画、平滑过渡到新目标”的逻辑,非常适合鼠标跟随、拖拽预览等场景。


✅ 2. gsap.utils.clamp()

🔍 是什么?

clamp(钳制/限制)是一个数值范围限制工具函数,确保一个值不会超出指定的最小值和最大值

📌 你的代码:

js

const clampX = gsap.utils.clamp(0, stage.clientWidth - 36);
const clampY = gsap.utils.clamp(0, stage.clientHeight - 36);
  • clampX 是一个函数,它接收一个数字,返回被限制在 [0, stage.clientWidth - 36] 范围内的值
  • -36 是因为你的 cursor 元素宽高为 36px(假设),要防止它超出容器右/下边缘

🎯 在事件中使用:

js

const x = clampX(event.clientX - rect.left - 18); // -18 是 cursor 宽度的一半(居中对齐)

✅ 作用:防止光标移出舞台区域

比如:

  • 舞台宽度是 500px,cursor 宽 36px → 最大允许 x = 500 - 36 = 464
  • 如果用户把鼠标移到 500px 处,clampX(500 - 18) = clampX(482) → 返回 464
  • 这样 cursor 就不会“跑出”舞台右边

🔁 等价于手写:

js

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

但 GSAP 的版本更简洁、可复用。


🧩 整体逻辑总结

“受限区域内的平滑自定义光标”

  1. 监听 #stage 的鼠标移动
  2. 计算鼠标相对于舞台的坐标clientX - rect.left
  3. 减去 18px 使光标中心对齐鼠标(假设光标是 36×36)
  4. 用 clamp 限制坐标,不让光标超出舞台边界
  5. 用 quickTo 高性能、平滑地更新光标位置

✅ 优势

技术 好处
gsap.quickTo 高频更新不卡顿,动画流畅,内存友好
gsap.utils.clamp 一行代码实现边界限制,代码清晰
GSAP 的 x/y 自动使用 transform,性能优于 left/top

💡 扩展建议

  • 如果想让光标在离开舞台时隐藏,可加:

    js

    stage.addEventListener("mouseleave", () => gsap.set(cursor, { autoAlpha: 0 }));
    stage.addEventListener("mouseenter", () => gsap.set(cursor, { autoAlpha: 1 }));
    
  • quickTo 也支持其他属性,如 scalerotationbackgroundColor 等。


✅ 总结

方法 作用
gsap.quickTo(target, prop, vars) 创建高性能属性更新器,适合高频调用
gsap.utils.clamp(min, max) 生成一个限制数值范围的函数,防止越界

这两个工具组合起来,是实现专业级交互动效(如自定义光标、拖拽预览、游戏 UI)的黄金搭档!

Draggable 是什么

  <div class="card">
      <h1>案例 14:Draggable 拖拽</h1>
      <p>拖动方块,体验 Draggable 的基础能力。</p>
      <div class="stage">
        <div class="drag" id="drag">拖我</div>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/Draggable.min.js"></script>
    <script>
      const drag = document.querySelector("#drag");

      // 注册 Draggable 插件
      gsap.registerPlugin(Draggable);

      // 创建可拖拽对象并限制在父容器内
      Draggable.create(drag, {
        type: "x,y",
        bounds: ".stage",
        inertia: false
      });
    </script>

DraggableGSAP(GreenSock Animation Platform)官方提供的一个强大插件,用于快速创建高性能、可定制的拖拽交互(drag-and-drop)。它不仅支持鼠标拖动,还完美兼容触摸设备(手机/平板),并内置了惯性滚动、边界限制、对齐吸附、旋转拖拽等高级功能。


📌 你的代码解释:

Draggable.create(drag, {
  type: "x,y",      // 允许水平和垂直拖动
  bounds: ".stage", // 限制拖拽范围在 .stage 容器内
  inertia: false    // 禁用惯性(松手后不会继续滑动)
});

这段代码的作用是:

#drag 元素变成一个可在 .stage 区域内自由拖动的方块,且松手后立即停止(无惯性滑动)。


Draggable 的核心能力

功能 说明
跨平台支持 自动适配鼠标 + 触摸(无需额外代码)
高性能 使用 transform(非 left/top),60fps 流畅拖拽
边界限制 (bounds) 可限制在父容器、自定义矩形区域或另一个元素内
惯性动画 (inertia) 松手后根据速度继续滑动(类似 iOS 滚动)
多种拖拽类型 (type) x(水平)、y(垂直)、x,y(自由)、rotation(旋转)、scroll(模拟滚动)等
事件回调 onDragStart, onDrag, onDragEnd 等,便于扩展逻辑
与其他 GSAP 动画无缝集成 拖拽过程中可触发 timeline、tween 等

🔧 常见配置项详解

1. type
  • "x":仅水平拖动
  • "y":仅垂直拖动
  • "x,y":自由二维拖动(最常用)
  • "rotation":围绕中心点旋转(适合旋钮、转盘)
  • "scrollTop" / "scrollLeft":模拟滚动条
2. bounds
  • 字符串选择器:".container" → 限制在该元素内
  • DOM 元素:document.body
  • 对象:{ top: 0, left: 0, width: 500, height: 300 }
3. inertia
  • true:松手后根据拖拽速度继续滑动(需加载 InertiaPlugin
  • false:松手立即停止(默认)

🎯 实际应用场景

场景 配置示例
可拖拽卡片 type: "x,y", bounds: ".card-container"
滑块/进度条 type: "x", bounds: ".slider-track"
旋转调节器 type: "rotation", bounds: { minRotation: 0, maxRotation: 180 }
图片裁剪框 type: "x,y", bounds: ".image"
游戏人物移动 type: "x,y", onDrag: updateCharacterPosition

💡 事件回调示例

Draggable.create(drag, {
  type: "x,y",
  bounds: ".stage",
  onDragStart: () => console.log("开始拖拽"),
  onDrag: () => console.log("正在拖拽", drag._gsap.x, drag._gsap.y),
  onDragEnd: () => console.log("拖拽结束")
});

📌 拖拽过程中的位置可通过 element._gsap.x / element._gsap.y 实时获取(GSAP 自动维护)。


⚠️ 注意事项

  1. 必须注册插件
    gsap.registerPlugin(Draggable);
    
  2. 被拖拽元素需定位:建议设置 position: absolutefixed,否则可能布局错乱。
  3. 避免与原生滚动冲突:在移动端可能需要 touch-action: none
    .drag {
      touch-action: none; /* 禁用浏览器默认拖拽/缩放 */
    }
    

当然可以!在 GSAP 的 Draggable 插件中,type 选项决定了拖拽行为的类型。以下是多个常见的 type 配置及其实际应用场景和代码示例,帮助你快速掌握不同拖拽模式的用法。


✅ 1. type: "x" —— 仅水平拖动

适用于滑块、时间轴、横向卡片流等。

Draggable.create(".slider-handle", {
  type: "x",
  bounds: ".slider-track" // 限制在轨道内
});

📌 效果:只能左右拖,不能上下移动。


✅ 2. type: "y" —— 仅垂直拖动

适用于音量条、滚动预览、垂直进度条。

Draggable.create(".volume-knob", {
  type: "y",
  bounds: ".volume-bar"
});

📌 效果:只能上下拖,不能左右移动。


✅ 3. type: "x,y" —— 自由二维拖动(最常用)

适用于可移动窗口、拖拽图标、自定义光标、游戏人物。

Draggable.create(".draggable-box", {
  type: "x,y",
  bounds: ".container" // 限制在容器内
});

📌 效果:可任意方向拖动,但不会超出 .container 边界。


✅ 4. type: "rotation" —— 旋转拖拽

适用于旋钮、转盘、角度调节器、图片旋转工具。

Draggable.create(".knob", {
  type: "rotation",
  bounds: { minRotation: 0, maxRotation: 270 } // 限制旋转角度
});

📌 效果:鼠标/手指绕元素中心旋转,值为角度(°)。

💡 元素需设置 transform-origin: center(默认即是)。


✅ 5. type: "scrollTop" —— 模拟垂直滚动

适用于自定义滚动条、迷你地图导航。

// 拖动小方块控制大内容区滚动
Draggable.create(".scroll-thumb", {
  type: "scrollTop",
  scrollElement: document.querySelector(".content") // 要滚动的目标元素
});

📌 效果:拖动 .scroll-thumb 时,.content 区域会同步垂直滚动。


✅ 6. type: "scrollLeft" —— 模拟水平滚动

适用于横向长图浏览、时间线导航。

Draggable.create(".horizontal-thumb", {
  type: "scrollLeft",
  scrollElement: document.querySelector(".timeline")
});

📌 效果:拖动 thumb 控制 .timeline 水平滚动。


✅ 7. type: "top,left" —— 使用 top/left 定位(不推荐)

⚠️ 性能较差,仅用于特殊布局(如非 transform 兼容场景)。

Draggable.create(".legacy-element", {
  type: "top,left",
  bounds: ".parent"
});

📌 区别

  • 默认 x,y 使用 transform: translate()(高性能、不影响文档流)
  • top,left 直接修改 CSS top/left(触发重排,性能低)

建议优先使用 x,y


✅ 8. 组合类型(GSAP 3.12+ 支持)—— type: "x,rotation"

同时支持水平移动 + 旋转(高级交互)。

Draggable.create(".dial", {
  type: "x,rotation",
  bounds: { minX: 0, maxX: 300 }
});

📌 效果:左右拖动改变位置,同时可旋转(需配合手势或逻辑判断)。

🔔 注意:组合类型需明确指定每个维度的行为,实际使用较少。


🎯 补充:如何读取拖拽状态?

无论哪种 type,你都可以通过以下方式获取实时值:

const drag = Draggable.get(".element");

console.log(drag.x);        // 当前 x 位移(px)
console.log(drag.y);        // 当前 y 位移(px)
console.log(drag.rotation); // 当前旋转角度
console.log(drag.scrollY);  // 当前 scrollTop 值(如果 type 是 scrollTop)

✅ 总结:常用 type 对照表

type 用途 是否常用
"x" 水平滑块 ✅ 高频
"y" 垂直滑块 ✅ 高频
"x,y" 自由拖拽(窗口/图标) ✅ 最常用
"rotation" 旋钮、转盘 ✅ 中频
"scrollTop" 自定义垂直滚动条 ✅ 中频
"scrollLeft" 自定义水平滚动条 ✅ 中频
"top,left" 兼容旧布局(不推荐) ❌ 少用

通过合理选择 type,你可以用极少的代码实现丰富的交互效果。结合 boundsinertia、事件回调(onDrag 等),Draggable 几乎能满足所有拖拽需求!

✅ 总结

术语 含义
Draggable GSAP 官方拖拽插件,提供高性能、跨平台、可定制的拖拽交互能力

代码是一个典型的 “受限区域内的基础拖拽” 示例,非常适合入门。通过组合 boundstypeinertia 和事件回调,你可以轻松实现从简单 UI 控件到复杂游戏交互的各种需求。

gsap 配置解读 --1

作者 大时光
2026年2月13日 10:56

toggleActions: "play none none reverse" 是什么意思

gsap.to(panel, {
y: 0,
opacity: 1,
duration: 0.8,
ease: "power2.out", 
scrollTrigger: {
trigger: panel, 
start: "top 80%", // 当 panel 的顶部到达 viewport 的 80% 位置时,进入触发区
end: "top 40%", // 当 panel 的顶部到达 viewport 的 40% 位置时,离开触发区 
toggleActions: "play none none reverse"
} 
});
位置 触发时机 说明
1. onEnter 元素从上往下滚动进入触发区间(比如进入 startend 区域) 此处是 "play" → 播放动画
2. onLeave 元素继续向下滚动,离开触发区间(滚出 end 之后) 此处是 "none" → 什么都不做
3. onEnterBack 元素从下往上滚动,重新进入触发区间(反向滚动进入) 此处是 "none" → 什么都不做
4. onLeaveBack 元素继续向上滚动,离开触发区间(反向滚出 start 之前) 此处是 "reverse" → 反向播放动画(即倒放)

toggleActions

动作值 效果
"play" 播放动画(从当前进度开始)
"pause" 暂停动画
"resume" 恢复播放(如果已暂停)
"reverse" 反向播放(倒放)
"restart" 从头开始播放
"reset" 重置到初始状态
"none" 无操作(保持当前状态)

 典型使用场景对比:

需求 推荐 toggleActions
进入播放,离开重置 "play none none reset"
进入播放,反向离开时倒放 "play none none reverse" ← 你的情况
只播放一次,之后不再动 "play pause pause pause"
来回都播放 "play play play play"(不推荐,会闪烁)

paused: true是什么意思

{
x: 280, 
scale: 0.5,
opacity: 0,
duration: 1,
ease: "power2.out",
paused: true 
});

在 GSAP(GreenSock Animation Platform)中,paused: true 是一个动画配置选项,它的作用是:

创建动画时立即暂停(不自动播放),等待后续手动控制播放。

  • gsap.from(...) 表示:从指定的起始状态(x=280, scale=0.5, opacity=0)动画到元素当前的 CSS 状态
  • 但由于设置了 paused: true,这个动画不会立刻执行,而是被“冻结”在初始状态(即元素保持原样,不会动)。
  • 你需要手动调用 tween.play() 才会开始播放动画。

✅ 为什么需要 paused: true

通常用于以下场景:

1. 延迟触发动画

比如点击按钮、滚动到某位置、或满足某个条件后再播放:

document.querySelector('#btn').addEventListener('click', () => { 
tween.play(); // 点击时才播放
});
2. 配合 ScrollTrigger 或其他交互逻辑

你可能先定义好动画,等 ScrollTrigger 初始化完成后再关联:

ScrollTrigger.create({
trigger: ".section",
start: "top center",
onEnter: () => tween.play()
});
3. 复用动画

同一个 tween 可以多次 play()reverse()restart(),而不会重复创建。

方法 作用
tween.play() 播放动画
tween.pause() 暂停动画
tween.reverse() 反向播放(从当前进度倒放回起点)
tween.restart() 从头开始播放
tween.seek(0.5) 跳转到动画 50% 进度
tween.progress(1) 瞬间跳到结束状态
配置 含义
paused: true 创建动画但不自动播放,需手动调用 .play() 等方法控制
默认(不写) 动画创建后立即自动播放

gsap.set() set 是什么意思

在 GSAP(GreenSock Animation Platform)中,gsap.set() 是一个立即设置元素属性的方法,不会产生动画过渡,而是瞬间应用指定的样式或属性值

方法 是否动画 用途
gsap.set(target, vars) ❌ 否 立即设置属性(相当于“初始化状态”)
gsap.to(target, vars) ✅ 是 从当前状态 动画到 指定状态
gsap.from(target, vars) ✅ 是 从指定状态 动画到 当前状态
gsap.fromTo(target, fromVars, toVars) ✅ 是 自定义起始和结束状态

clearProps: "all"是什么意思

gsap.set([boxA, boxB], { clearProps: "all" }); 这行代码的作用是:

立即清除 boxA 和 boxB 元素上由 GSAP 设置的所有内联样式属性(比如 transformopacitybackgroundColor 等),让它们恢复到 GSAP 干预之前的状态(即仅受 CSS 类或原始 HTML 样式控制)。


✅ clearProps 的作用详解

  • GSAP 在执行动画(如 gsap.to()gsap.from())或 gsap.set() 时,会直接写入元素的 style 属性(例如:<div style="transform: translateX(100px); opacity: 0.5;">)。
  • 这些内联样式优先级很高,会覆盖你写的 CSS 类。
  • 使用 clearProps 可以清理这些“残留”的内联样式,避免干扰后续布局或样式。
说明
"all" 清除 所有 GSAP 设置过的内联样式(最常用)✅
"transform" 仅清除 transform 相关属性(如 x, y, scale, rotation 等)
"opacity,backgroundColor" 清除指定的多个属性(用逗号分隔)
"x,y" 仅清除 xy(即 transform: translateX/Y

💡 注意:clearProps 只清除 GSAP 显式设置过 的属性,不会影响其他 JavaScript 或 HTML 中原本就有的 style

🎯 使用场景举例

场景 1:重置动画状态

js

// 先执行一个动画
gsap.to(boxA, { x: 100, backgroundColor: "red", duration: 1 });

// 后来想让它完全回到原始 CSS 样式
gsap.set(boxA, { clearProps: "all" });
// 效果相当于:boxA.style.cssText = ""; (但更安全,只清 GSAP 设置的)
场景 2:避免 transform 冲突

css

.my-box {
  transform: rotate(10deg); /* 原始 CSS transform */
}

js

gsap.to(".my-box", { x: 50 }); // GSAP 会合并 transform,变成 rotate + translate
gsap.set(".my-box", { clearProps: "transform" }); // 清除后,只剩 rotate(10deg)
场景 3:组件销毁前清理

在 React/Vue 组件卸载时,清除 GSAP 添加的样式,防止内存泄漏或样式残留。


⚠️ 注意事项

  1. clearProps: "all" 不会删除非 GSAP 设置的内联样式
    比如你手动写了 <div style="color: blue">,GSAP 不会动它。
  2. transform 是一个整体
    即使你只设置了 x: 100clearProps: "transform" 也会清除整个 transform 字符串。
  3. autoAlpha 会同时影响 opacity 和 visibility
    如果你用了 autoAlpha,需要同时清除这两个属性。
代码 作用
gsap.set(el, { clearProps: "all" }) 彻底清除 GSAP 对该元素设置的所有内联样式,恢复“干净”状态

keyframes是什么意思

const tween = gsap.to(shape, {
        keyframes: [
          { x: -160, rotation: -15, duration: 0.4 },
          { x: 0, scale: 1.2, duration: 0.4 },
          { x: 160, rotation: 20, duration: 0.4 },
          { x: 0, scale: 1, rotation: 0, duration: 0.4 }
        ],
        ease: "power1.inOut",
        paused: true
      });

在 GSAP(GreenSock Animation Platform)中,keyframes 是一种将多个动画步骤串联起来的方式,类似于 CSS 的 @keyframes,但功能更强大、更灵活。

这段代码的意思是:

对 shape 元素执行一个由 4 个关键帧组成的复合动画,每个关键帧持续 0.4 秒,总共 1.6 秒。动画被暂停(paused: true),需手动调用 .play() 才会运行。


✅ keyframes 的工作原理

  • 每个对象代表一个动画阶段(关键帧)
  • GSAP 会按顺序依次播放这些关键帧。
  • 每一帧的属性是从上一帧的结束状态过渡到当前帧的目标值。
  • 每帧可以有自己的 durationease(如果未指定,则继承外层的 ease)。
动画流程分解:
阶段 起始状态 → 目标状态 效果
第1帧 当前状态 → {x: -160, rotation: -15} 向左飞 + 左转
第2帧 上一帧结束 → {x: 0, scale: 1.2} 回到中心 + 放大
第3帧 上一帧结束 → {x: 160, rotation: 20} 向右飞 + 右转
第4帧 上一帧结束 → {x: 0, scale: 1, rotation: 0} 回到原位 + 还原大小和角度

🔧 keyframes 的高级用法

1. 每帧可单独设置缓动(ease)

js

keyframes: [
  { x: 100, duration: 0.3, ease: "back.out" },
  { x: 0, duration: 0.3, ease: "elastic.out" }
]
2. 支持回调函数

js

keyframes: [
  { x: 100, duration: 0.5 },
  { 
    x: 0, 
    duration: 0.5,
    onComplete: () => console.log("第二帧完成") 
  }
]
3. 与 ScrollTrigger、Timeline 结合

js

gsap.timeline({
  scrollTrigger: { trigger: ".section", start: "top center" }
}).to(shape, {
  keyframes: [ /* ... */ ]
});

⚠️ 注意事项

  • keyframes 是 GSAP 3.0+  引入的功能,在旧版本中不可用。
  • 外层的 ease(如你的 "power1.inOut")会作为默认缓动应用到每一帧(除非某帧自己指定了 ease)。
  • 如果某帧没有指定 duration,它会继承前一帧的 duration 或使用默认值(通常为 0.3 秒)。

✅ 为什么用 keyframes 而不用多个 gsap.to()

表格

方式 优点
keyframes 代码更紧凑,自动串联,易于管理单个动画序列
多个 gsap.to() 更灵活(可插入延迟、回调等),适合复杂编排(推荐用 gsap.timeline()

对于简单的线性多步动画,keyframes 非常简洁;对于复杂时间轴,建议用 gsap.timeline()


keyframes = 把多个动画步骤写在一个数组里,GSAP 自动按顺序播放它们。

你的代码创建了一个“左右晃动 + 缩放”的弹性动画,常用于:

  • 按钮点击反馈
  • 错误提示抖动
  • 卡片翻转/弹跳效果

配合 paused: true,你可以在需要时(如点击、滚动)通过 tween.play() 触发动画,非常高效!

stagger 是什么意思

在 GSAP(GreenSock Animation Platform)中,stagger 是一个非常强大的功能,用于对多个目标元素(如数组、NodeList)依次错开播放动画,从而创建出“波浪式”、“逐个入场”等流畅的序列动画效果。

 const tween = gsap.from(cells, {
        opacity: 0,
        scale: 0.4,
        y: 20,
        duration: 0.6,
        ease: "power2.out",
       stagger: { 
           each: 0.04, // 每个元素之间的延迟时间(秒)
           from: "center" // 动画从中间的元素开始,向两边扩散
       },
        paused: true
      });

这段代码的作用是:

对 cells(一组 DOM 元素)执行“从透明、缩小、下移”状态淡入放大的动画,但不是同时播放,而是:

  • 从中间的元素开始
  • 相邻元素之间间隔 0.04 秒依次播放
  • 整体形成一种“由中心向外扩散”的入场效果 ✨

✅ stagger 的核心概念

当你对多个元素(如 document.querySelectorAll('.cell'))使用 GSAP 动画时:

  • 不加 stagger → 所有元素同时动画。
  • 加上 stagger → 元素依次错开动画,产生节奏感。

🔧 stagger 的常见写法

1. 最简形式:只指定间隔时间

js

stagger: 0.1  // 等价于 { each: 0.1 }

→ 从第一个元素开始,每个间隔 0.1 秒。

2. 对象形式(你用的方式):更精细控制

js

stagger: {
  each: 0.04,     // 每个元素间隔 0.04 秒
  from: "center", // 起始位置:可选 "start"(默认)、"center""end" 或具体索引(如 3)
  grid: "auto",   // 如果是网格布局,可设为 [rows, cols] 来按行/列交错
  axis: "x"       // 在网格中限制交错方向("x""y""xy")
}

🎯 from 的取值说明

效果
"start"(默认) 从第一个元素开始,依次到最后一个
"center" 从中间元素开始,向左右(或上下)同时扩散
"end" 从最后一个元素开始,倒序播放
数字(如 2) 从索引为 2 的元素开始

✅  from: "center" 非常适合居中对齐的列表、图标阵列、卡片网格等场景,视觉上更平衡。


💡 实际效果示例

假设 cells 有 5 个元素:[A, B, C, D, E]

  • from: "center" → 播放顺序:C → B & D → A & E
  • 每个间隔 0.04s,所以整个动画在约 0.04 × 2 = 0.08s 内完成扩散(因为两边并行)

这比线性播放(A→B→C→D→E)更生动!


⚠️ 注意事项

  • stagger 只在目标是多个元素时生效。如果 cells 只有一个元素,stagger 会被忽略。
  • stagger 的延迟是叠加在 duration 之上的,不影响单个动画的时长。
  • 可与 paused: true 完美配合,实现“按需触发动画序列”。

配置 含义
stagger: { each: 0.04, from: "center" } 从中间元素开始,以 0.04 秒的间隔向两侧依次播放动画

这是 GSAP 实现高级交互动效(如列表加载、菜单展开、数据可视化入场)的核心技巧之一。你的代码就是一个典型的“优雅批量入场”动画!

❌
❌