mcpField
S
svg-animations

svg-animations

github.com/supermemoryaiデザイン・UI1132.6k 回インストール2 週間前に更新
リポジトリ

svg-animations について

svg-animationsは、アニメーションアイコンから複数段階のパス表現まで、SVGアニメーション制作を支援するスキルです。SVGの構造と、CSSおよびネイティブSMILによる手法を解説します。

主な機能

  1. 01SVGのパス、図形、座標系
  2. 02CSSによる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):2 つの制御点で曲線を定義します。最初の制御点で曲線の出発角度を、2 つ目で到着角度を設定します。

<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 の多くの属性は、fill、stroke、opacity、transform、stroke-dasharray、stroke-dashoffset など、有効な CSS プロパティです。

基本的な 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 にパスの全長を設定します(巨大な破線 1 つと巨大な間隔 1 つ)
  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. SVG では viewBox を使用し、width/height をハードコードしないでください — サイズはコンテナーに任せます。これにより、解像度に依存しなくなります。

  2. 再利用可能な定義には <defs> を使用してください — グラデーション、フィルター、マスク、clipPath、再利用可能な図形は <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;
  }
}

コメント