gsap 配置解读 --3

drawSVG 是什么

js 复制代码
  <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> 等),实现类似"手绘"、"描边动画"的效果。


📌 你的代码解释:

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

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

⚠️ 注意事项

  1. 必须注册插件

    js 复制代码
    gsap.registerPlugin(DrawSVGPlugin);
  2. 路径必须是"单一线条"

    复杂组合路径(如多个子路径)可能表现异常,建议简化或拆分。

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

  4. 与 ScrollTrigger 结合极佳

    常用于"滚动触发动画":

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

✅ 总结

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

EaselPlugin是什么

js 复制代码
<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 来更新舞台)

🔍 你的代码逐行解析

js 复制代码
// 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();
js 复制代码
// 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
});
js 复制代码
// 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)),但需启用:

    js 复制代码
    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 是什么

js 复制代码
<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 会自动检测差异并补间!


📌 你的代码解释:

js 复制代码
// 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(推荐用于动态列表)
js 复制代码
// 给每个 item 加 data-id
<div class="item" data-flip-id="A">A</div>

// Flip 会按 data-flip-id 匹配元素
Flip.from(state, { 
  absolute: true, // 使用绝对定位避免布局抖动
  simple: true    // 简化动画(仅位移+缩放)
});
2. 处理新增/删除元素
js 复制代码
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(),实现声明式布局动画。


⚠️ 注意事项

  • 必须注册插件

    js 复制代码
    gsap.registerPlugin(Flip);
  • 元素需有明确尺寸和位置 (避免 display: none 或未渲染状态)

  • 默认使用相对定位 ,若布局跳动可加 absolute: true

  • 不适用于纯颜色/文本内容变化(那是 CSS Transition 的领域)


✅ 总结

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

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

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

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

什么是GSDevTools

js 复制代码
 <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>

什么是 InertiaPlugin

js 复制代码
<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是什么

js 复制代码
<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)、重复等高级功能。

js 复制代码
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 中实现"路径动画"的核心工具,让复杂轨迹运动变得简单、流畅且高度可控。

相关推荐
兰亭古墨1 小时前
钉钉工作台自建组件定时器被禁?用 Swiper 模拟 setInterval 的优雅方案
前端·钉钉
phltxy2 小时前
Vue核心进阶:v-model深度解析+ref+nextTick实战
前端·javascript·vue.js
三小河2 小时前
React 样式——styled-components
前端·javascript·后端
Hi_MrXiao2 小时前
电脑上安装使用多个版本的谷歌浏览器
前端·chrome
广州华水科技2 小时前
单北斗GNSS变形监测一体机在大坝安全监测中的应用探索
前端
colicode2 小时前
C++语音验证码接口API示例代码详解:高性能C++语音校验接入Demo
前端·c++·前端框架·语音识别
We་ct2 小时前
LeetCode 92. 反转链表II :题解与思路解析
前端·算法·leetcode·链表·typescript
Wect2 小时前
LeetCode 92. 反转链表II :题解与思路解析
前端·算法·typescript
Wect2 小时前
LeetCode 138. 随机链表的复制:两种最优解法详解
前端·算法·typescript