mcpField
S
svg-animations

svg-animations

github.com/supermemoryai设计与 UI1132.6k 次安装2 周前更新
代码仓库

关于 svg-animations

svg-animations 是一项手工制作 SVG 动画的技能,适用于动态图标和多阶段路径动画。内容涵盖 SVG 结构,以及 CSS 与原生 SMIL 动画方法。

主要功能

  1. 01SVG 路径、形状与坐标系
  2. 02基于 CSS 的 SVG 动画
  3. 03原生 SMIL 动画方法
  4. 04路径描绘与形状变形
  5. 05动画时序、缓动与同步
  6. 06性能与无障碍指导

适用场景

  1. 01制作动态图标和标志
  2. 02创建路径动画与多阶段序列
  3. 03为内联或嵌入式 SVG 添加动效
  4. 04减少动态效果并提升 SVG 无障碍性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/supermemoryai/skills --skill svg-animations

安装后在 Claude Code 中输入/svg-animations确认已加载。

详细介绍

此技能介绍如何制作手工 SVG 动画——从简单的动画图标到复杂的多阶段路径动画。SVG 是一种图像标记语言;每个元素都是一个可以设置样式、添加动画和编写脚本的 DOM 节点。

SVG 基础

坐标系

SVG 使用由 viewBox="minX minY width height" 定义的坐标系。viewBox 就是画布——所有坐标都相对于它,因此 SVG 与分辨率无关。

<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
  
</svg>
基本图形
<rect x="10" y="10" width="80" height="40" rx="4" fill="#1a1a1a" />
<circle cx="50" cy="50" r="30" fill="#e63946" />
<ellipse cx="50" cy="50" rx="40" ry="20" fill="#457b9d" />
<line x1="10" y1="10" x2="90" y2="90" stroke="#2a9d8f" stroke-width="2" />
<polygon points="50,5 95,90 5,90" fill="#e9c46a" />
<polyline points="10,80 40,20 70,60 100,10" fill="none" stroke="#264653" stroke-width="2" />
<path> 元素——强大工具

d 属性使用命令定义路径。大写字母表示绝对坐标,小写字母表示相对坐标。

命令用途语法
M/m移动到M x y
L/l绘制直线到L x y
H/h绘制水平线H x
V/v绘制垂直线V y
C/c三次贝塞尔曲线C x1 y1, x2 y2, x y
S/s平滑三次贝塞尔曲线S x2 y2, x y
Q/q二次贝塞尔曲线Q x1 y1, x y
T/t平滑二次贝塞尔曲线T x y
A/a椭圆弧A rx ry rotation large-arc sweep x y
Z/z闭合路径Z

三次贝塞尔曲线(C):两个控制点定义曲线。第一个控制点决定曲线的起始方向,第二个控制点决定曲线的结束方向。

<path d="M 10 80 C 40 10, 65 10, 95 80" stroke="#000" fill="none" stroke-width="2" />

平滑三次贝塞尔曲线(S):自动镜像上一个控制点,非常适合串联流畅的 S 形曲线。

<path d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="#000" fill="none" />

圆弧(A):rx ry x-rotation large-arc-flag sweep-flag x y

  • large-arc-flag:0 = 小弧,1 = 大弧(>180°)
  • sweep-flag:0 = 逆时针,1 = 顺时针

<path d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 Z"
      fill="#e63946" />
分组和变换
<g transform="translate(50, 50) rotate(45)" opacity="0.8">
  <rect x="-20" y="-20" width="40" height="40" fill="#264653" />
</g>

使用 <g> 将元素分组,以便统一应用变换、样式和动画。

渐变、蒙版和滤镜
<defs>
  
  <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
    <stop offset="0%" stop-color="#e63946" />
    <stop offset="100%" stop-color="#457b9d" />
  </linearGradient>

  
  <radialGradient id="glow" cx="50%" cy="50%" r="50%">
    <stop offset="0%" stop-color="#fff" stop-opacity="0.8" />
    <stop offset="100%" stop-color="#fff" stop-opacity="0" />
  </radialGradient>

  
  <mask id="reveal">
    <rect width="100%" height="100%" fill="black" />
    <circle cx="100" cy="100" r="50" fill="white" />
  </mask>

  
  <filter id="blur">
    <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
  </filter>
</defs>

<rect width="200" height="200" fill="url(#grad)" />
<rect width="200" height="200" fill="url(#grad)" mask="url(#reveal)" />
<circle cx="50" cy="50" r="20" filter="url(#blur)" fill="#e63946" />

SVG 上的 CSS 动画

许多 SVG 属性都是有效的 CSS 属性:fill、stroke、opacity、transform、stroke-dasharray、stroke-dashoffset 等。

基本 CSS 动画
.pulse {
  animation: pulse 2s ease-in-out infinite;
  transform-origin: center;
}
@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.15); opacity: 0.7; }
}
描边绘制动画(经典效果)

最具代表性的 SVG 动画。它使用 stroke-dasharray 和 stroke-dashoffset,让路径看起来像是自行绘制出来的。

工作原理:

  1. 将 stroke-dasharray 设为路径的总长度(一个超长的虚线段加一个超长的间隙)
  2. 将 stroke-dashoffset 设为相同的长度(将虚线段移出屏幕)
  3. 将 stroke-dashoffset 动画到 0(让虚线段滑入视野)
<svg viewBox="0 0 200 200">
  <path class="draw" d="M 20 100 C 20 50, 80 50, 80 100 S 140 150, 140 100"
        fill="none" stroke="#1a1a1a" stroke-width="3" />
</svg>

<style>
  .draw {
    stroke-dasharray: 300;
    stroke-dashoffset: 300;
    animation: draw 2s ease forwards;
  }
  @keyframes draw {
    to { stroke-dashoffset: 0; }
  }
</style>

使用 JS 获取精确的路径长度:

const path = document.querySelector('.draw');
const length = path.getTotalLength();
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
多路径交错绘制
.line-1 { animation-delay: 0s; }
.line-2 { animation-delay: 0.3s; }
.line-3 { animation-delay: 0.6s; }
CSS d 属性动画

现代浏览器支持直接在 CSS 中为 d 属性添加动画:

path {
  d: path("M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z");
  transition: d 0.5s ease;
}
path:hover {
  d: path("M 10,50 A 20,20 0,0,1 50,10 A 20,20 0,0,1 90,50 Q 90,80 50,100 Q 10,80 10,50 z");
}

要求: 两条路径必须包含数量和类型相同的命令,才能进行插值。


SMIL 动画(原生 SVG)

SMIL 动画直接在 SVG 标记中声明。即使 SVG 作为 <img> 或 CSS background-image 加载时(此时 CSS 和 JS 无法访问它),动画也能正常运行。

<animate>——为任意属性添加动画
<circle cx="50" cy="50" r="20" fill="#e63946">
  <animate attributeName="r" from="20" to="40" dur="1s"
           repeatCount="indefinite" />
</circle>

使用关键帧:

<animate attributeName="cx"
         values="50; 150; 100; 50"
         keyTimes="0; 0.33; 0.66; 1"
         dur="3s" repeatCount="indefinite" />
<animateTransform>——变换动画
<rect x="-20" y="-20" width="40" height="40" fill="#264653">
  <animateTransform attributeName="transform" type="rotate"
                    from="0" to="360" dur="4s" repeatCount="indefinite" />
</rect>

类型:translate、scale、rotate、skewX、skewY

<animateMotion>——沿路径移动
<circle r="5" fill="#e63946">
  <animateMotion dur="3s" repeatCount="indefinite" rotate="auto">
    <mpath href="#motionPath" />
  </animateMotion>
</circle>
<path id="motionPath" d="M 20,50 C 20,0 80,0 80,50 S 140,100 140,50"
      fill="none" stroke="#ccc" />

rotate="auto" 会让元素沿路径切线方向旋转。rotate="auto-reverse" 会将其翻转 180°。

<set>——离散值变化
<rect width="40" height="40" fill="#264653">
  <set attributeName="fill" to="#e63946" begin="1s" />
</rect>
计时和同步

<animate id="first" attributeName="cx" to="150" dur="1s" fill="freeze" />
<animate attributeName="cy" to="150" dur="1s" begin="first.end" fill="freeze" />
<animate attributeName="r" to="30" dur="0.5s" begin="first.end + 0.5s" fill="freeze" />

触发值:

  • begin="click" — 点击时
  • begin="2s" — 2 秒后
  • begin="other.end" — 另一动画结束时
  • begin="other.end + 1s" — 另一动画结束 1 秒后
  • begin="other.repeat(2)" — 另一动画第 2 次重复时
使用 calcMode 和 keySplines 缓动
<animate attributeName="cx" values="50;150" dur="1s"
         calcMode="spline" keySplines="0.42 0 0.58 1" />

calcMode 选项:linear(默认)、discrete、paced、spline

keySplines 接受每个时间间隔对应的三次贝塞尔控制点(x1 y1 x2 y2)。常见的缓动效果:

  • 缓入缓出:0.42 0 0.58 1
  • 缓出:0 0 0.58 1
  • 类似弹跳:0.34 1.56 0.64 1
使用 SMIL 进行图形变形

两个图形必须具有相同的命令结构(点数和命令类型相同):

<path fill="#e63946">
  <animate attributeName="d" dur="2s" repeatCount="indefinite"
    values="M 50,10 L 90,90 L 10,90 Z;
            M 50,90 L 90,10 L 10,10 Z;
            M 50,10 L 90,90 L 10,90 Z" />
</path>

动画模式与示例

加载旋转图标
<svg viewBox="0 0 50 50">
  <circle cx="25" cy="25" r="20" fill="none" stroke="#1a1a1a"
          stroke-width="3" stroke-linecap="round"
          stroke-dasharray="90 150" stroke-dashoffset="0">
    <animateTransform attributeName="transform" type="rotate"
                      from="0 25 25" to="360 25 25" dur="1s"
                      repeatCount="indefinite" />
    <animate attributeName="stroke-dashoffset" values="0;-280"
             dur="1.5s" repeatCount="indefinite" />
  </circle>
</svg>
动画对勾
<svg viewBox="0 0 52 52">
  <circle cx="26" cy="26" r="24" fill="none" stroke="#4caf50"
          stroke-width="2" class="draw"
          style="stroke-dasharray:150;stroke-dashoffset:150;
                 animation:draw .6s ease forwards" />
  <path fill="none" stroke="#4caf50" stroke-width="3"
        stroke-linecap="round" stroke-linejoin="round"
        d="M14 27l7 7 16-16" class="draw"
        style="stroke-dasharray:50;stroke-dashoffset:50;
               animation:draw .4s ease .5s forwards" />
</svg>
从汉堡菜单图标变为 X
<svg viewBox="0 0 24 24" id="menu">
  <path id="top" d="M 3,6 L 21,6" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round">
    <animate attributeName="d" to="M 5,5 L 19,19" dur="0.3s" begin="menu.click" fill="freeze" />
  </path>
  <path id="mid" d="M 3,12 L 21,12" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round">
    <animate attributeName="opacity" to="0" dur="0.1s" begin="menu.click" fill="freeze" />
  </path>
  <path id="bot" d="M 3,18 L 21,18" stroke="#1a1a1a" stroke-width="2" stroke-linecap="round">
    <animate attributeName="d" to="M 5,19 L 19,5" dur="0.3s" begin="menu.click" fill="freeze" />
  </path>
</svg>
渐变动画(颜色变化)
<defs>
  <linearGradient id="shift" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%">
      <animate attributeName="stop-color"
               values="#e63946;#457b9d;#2a9d8f;#e63946"
               dur="4s" repeatCount="indefinite" />
    </stop>
    <stop offset="100%">
      <animate attributeName="stop-color"
               values="#457b9d;#2a9d8f;#e63946;#457b9d"
               dur="4s" repeatCount="indefinite" />
    </stop>
  </linearGradient>
</defs>
<rect width="200" height="100" fill="url(#shift)" rx="8" />
呼吸 / 脉冲光效
<circle cx="100" cy="100" r="30" fill="#e63946">
  <animate attributeName="r" values="30;35;30" dur="2s"
           calcMode="spline" keySplines="0.4 0 0.6 1;0.4 0 0.6 1"
           repeatCount="indefinite" />
  <animate attributeName="opacity" values="1;0.6;1" dur="2s"
           calcMode="spline" keySplines="0.4 0 0.6 1;0.4 0 0.6 1"
           repeatCount="indefinite" />
</circle>
波浪 / 液体效果
<path fill="#457b9d" opacity="0.7">
  <animate attributeName="d" dur="5s" repeatCount="indefinite"
    values="M 0,40 C 30,35 70,45 100,40 L 100,100 L 0,100 Z;
            M 0,40 C 30,50 70,30 100,40 L 100,100 L 0,100 Z;
            M 0,40 C 30,35 70,45 100,40 L 100,100 L 0,100 Z"
    calcMode="spline" keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
</path>

最佳实践

  1. 使用 viewBox,不要在 SVG 中硬编码 width/height——让容器决定尺寸。这样可以保持分辨率无关性。

  2. 使用 <defs> 存放可复用的定义——渐变、滤镜、蒙版、剪切路径和可复用图形都应放在 <defs> 中。

  3. 独立 SVG(通过 <img> 加载的图标、徽标)优先使用 SMIL——CSS / JS 在这种情况下不起作用。如果 SVG 是内联的,并且需要与页面其余部分协调,则使用 CSS 动画。

  4. 形状变形需要匹配的命令——路径命令的数量、类型和顺序都必须相同。如果形状不同,可添加不可见的中间点以保持一致。

  5. stroke-linecap="round" 可让线条动画看起来更精致。

  6. SMIL 中的 fill="freeze" 会保留动画的最终状态。没有它,元素会恢复到原始状态。

  7. 在 CSS 中设置 transform-origin: center——SVG 变换默认以原点(0,0)为基准,而不是元素中心。务必显式设置此属性。

  8. 在 JS 中使用 getTotalLength() 获取精确的路径长度,用于描边动画,而不是凭估算。

  9. 使用 <g> 组分层制作动画——对于复杂的编排,分别为组变换和单个元素属性制作动画。

  10. **性能:**为 transform 和 opacity 制作动画时,SVG 动画会由 GPU 合成。为 d、points 或布局属性制作动画会触发重绘,因此在复杂 SVG 中应谨慎使用。

  11. 在带动画的 SVG 元素上设置 will-change: transform 有助于浏览器优化合成。

  12. **无障碍:**添加 role="img" 和 <title> / <desc> 元素。使用 prefers-reduced-motion 媒体查询,为希望关闭动画的用户禁用动画:

@media (prefers-reduced-motion: reduce) {
  svg * {
    animation: none !important;
    transition: none !important;
  }
}

评论

支持 Markdown