mcpField
S
svg-animation

svg-animation

github.com/iart-aiデザイン・UI632.7k 回インストール18 週間前に更新
リポジトリ

svg-animation について

SVGアイコン、イラスト、ロゴ、データマークのアニメーションを扱うスキルです。CSS、SMIL、JavaScriptによる線の描画、パスの変形、パス上の移動に加え、最適化と動きを減らす設定への対応を説明します。

主な機能

  1. 01線を描くアニメーション
  2. 02SVGパスの変形
  3. 03パスに沿った移動
  4. 04グラデーションとフィルターのアニメーション
  5. 05SVGの最適化とアクセシビリティ

活用シーン

  1. 01アイコンの状態切り替えアニメーション
  2. 02署名や地図を描くアニメーション
  3. 03ロゴやデータマークへの動きの追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/iart-ai/web-animation-skills --skill svg-animation

インストール後、Claude Code で/svg-animationを入力して読み込まれたか確認します。

同梱ファイルREADME.mdreferences/svg-techniques.md

詳細

SVG アニメーション

鮮明で軽量、無限に拡大・縮小できるベクターの動きです。アイコン、イラスト、ロゴ、データマークに最適です。SVG は CSS(宣言的でシンプル)、SMIL(SVG 内の <animate>)、JS(制御やモーフィング向けの GSAP/Web Animations)の 3 通りでアニメーションできます。タスクに応じて選択してください。以下の手法には、それぞれの適用先が記載されています。

使用する場面

  • アイコン、イラスト、署名、地図のストロークを描き出すアニメーション
  • 図形やパスのモーフィング、アイコンの状態変化のアニメーション(メニュー ↔ 閉じる、再生 ↔ 一時停止)
  • パスに沿った要素の移動(モーションパス)
  • アニメーション付きグラデーション、フィルター(グロー、変位)、アニメーションロゴ

基本的な手法

ストロークを描き出す(定番)

ダッシュ配列をパスと同じ長さにし、オフセットを最大にして完全に非表示にしてから、オフセットを 0 までアニメーションさせます。

.path {
  stroke-dasharray: var(--len);
  stroke-dashoffset: var(--len);
  animation: draw 1.4s ease forwards;
}
@keyframes draw { to { stroke-dashoffset: 0; } }

長さの取得方法:

  • JS(最も確実):const len = path.getTotalLength(); path.style.setProperty("--len", len);
  • JS を使わない方法:<path> に pathLength="1" を設定し、stroke-dasharray: 1; stroke-dashoffset: 1; として、アニメーションで 0 にします。これにより、長さを測定せずにどのパスも 0~1 の長さに正規化できます。

オフセットを 0 から len にアニメーションさせると、逆向きに消去できます。複数のパスには animation-delay を設定して順番に開始します。描画方向はパスの点の順序に従います。逆向きに描画される場合は、エディターで順序を反転するか、オフセットの符号を反転してください。

あるパスから別のパスへのモーフィング

パスは点ごとに補間されるため、単純なモーフィングでは、両方の d 属性に同じ数と種類のコマンドが必要です。信頼性の高い方法は 2 つあります。

  • GSAP MorphSVG(GSAP 3.12 以降は無料)— 異なる点の数を自動的に処理し、適切な対応付けを行います。
gsap.registerPlugin(MorphSVGPlugin);
gsap.to("#start", { morphSVG: "#end", duration: 0.8, ease: "power2.inOut" });
// Convert any shape to a morph-able path:
MorphSVGPlugin.convertToPath("circle, rect, ellipse, line, polygon");
  • Flubber(小規模な単体ライブラリ)— GSAP を使わずに補間関数を生成できます。React/Framer Motion との併用に適しています。
import { interpolate } from "flubber";
const interpolator = interpolate(pathA, pathB, { maxSegmentLength: 2 });
// interpolator(0) === pathA, interpolator(1) === pathB; feed t into a tween.

手作業で作成するモーフィング(アイコンの切り替えなど)では、両方のパスのコマンド構造を同じにし、Web Animations または CSS で d を直接アニメーションさせます(最新のブラウザーでは、path("...") を使って d をアニメーションできます)。

パスに沿った移動
  • GSAP MotionPath(推奨 — 制御、位置合わせ、スクラブに対応):
gsap.registerPlugin(MotionPathPlugin);
gsap.to("#rocket", {
  duration: 4, repeat: -1, ease: "none",
  motionPath: { path: "#track", align: "#track", autoRotate: true, alignOrigin: [0.5, 0.5] },
});

autoRotate: true はオブジェクトの向きをパスの接線に合わせます。align を指定すると、座標がパス要素を基準にします。

  • SMIL(JS 不要):
<path id="track" d="M10,80 C40,10 120,10 150,80" fill="none"/>
<circle r="6" fill="#3b82f6">
  <animateMotion dur="3s" repeatCount="indefinite" rotate="auto">
    <mpath href="#track"/>
  </animateMotion>
</circle>
  • CSS の offset-path(最新の宣言的な方法):offset-path: path("M10,80 C..."); animation: move 3s linear infinite; と @keyframes move { to { offset-distance: 100%; } }、さらに offset-rotate: auto を指定します。
アニメーション付きグラデーションとフィルター

グラデーション:gradientTransform またはストップ位置をアニメーションさせます。光沢を走らせる例:

<linearGradient id="sheen">
  <stop offset="0%"  stop-color="#fff" stop-opacity="0"/>
  <stop offset="50%" stop-color="#fff" stop-opacity=".8"/>
  <stop offset="100%" stop-color="#fff" stop-opacity="0"/>
  <animateTransform attributeName="gradientTransform" type="translate"
    from="-1 0" to="1 0" dur="2s" repeatCount="indefinite"/>
</linearGradient>

フィルター:feDisplacementMap の scale をアニメーションさせて粘性や揺れを表現したり、feGaussianBlur の stdDeviation でフォーカスを移動したり、feColorMatrix/feFlood でグローを表現したりできます。フィルターは描画負荷が高いため、アニメーションは控えめにし、可能な場合は transform/opacity を優先してください。

実装方法の選択(すばやく選ぶ)

必要な機能使用するもの
単一の宣言的な描画/フェードCSS
自己完結型で、JS バンドル不要SMIL(SVG 内の <animate*>)
同期制御、スクラブ、スクロール連動GSAP
点の数が異なるモーフィングGSAP MorphSVG または Flubber
回転を伴うパス追従GSAP MotionPath/CSS offset-path

SMIL の注意点:IE/旧 Edge ではサポートされておらず、以前は非推奨化のフラグが設定されていました。幅広いブラウザーへの対応やスクロール同期が必要な場合は、CSS または JS を優先してください。最新ブラウザーで使う自己完結型のアイコンアセットには、引き続き SMIL が適しています。

作成と最適化

  • SVGO でビルド/クリーンアップします。viewBox は保持し、エディターのメタデータは削除します。ただし、cleanupIds/removeViewBox と、CSS/JS/SMIL から参照している ID の名前を変更するプラグインは無効にします。個々のサブパスやシェイプをアニメーションさせる場合は、mergePaths と convertShapeToPath も無効にします。
  • CSS/JS から内部要素にアクセスできるよう、SVG を DOM にインラインで埋め込みます(<img src> は使用しません)。<img> に埋め込んだ SVG は、内部の SMIL/CSS によるアニメーションのみ実行できます。
  • 明示的な viewBox を設定し、アセットが柔軟に拡大縮小できるよう、固定の width/height は避けます。
  • 描画アニメーションでは、パスが塗りつぶされたアウトラインではなく、実際のストローク(fill:none; stroke:...)であることを確認します。dashoffset が作用するのはストロークのみです。
  • prefers-reduced-motion に対応します。ループや大きな動きは制限し、静止した最終状態を維持します。

提供と検証(スタンドアロン HTML)

同梱ヘルパー(scripts/):scripts/seek-shot.sh anim.html 0 1.5 3 は ?t=N ハーネスでアニメーションを停止し、各時点のスクリーンショットを撮影します。scripts/contact-sheet.sh sheet.png frame-*.png はそれらをタイル状に並べ、一目で確認できるようにします。scripts/README.md を参照してください。

自己完結型のアイコン/ロゴ/描画アニメーションを提供する場合、成果物はブラウザーで直接開ける 1 つの HTML ファイルです。SVG をマークアップにインラインで埋め込み、アニメーションを 1 つの仕組みで制御し、ビルド工程は設けません。ベクターアセットには 1 ファイルが適切です。バンドラーは使わないでください。

出力要件:

  • .html ファイルを 1 つ用意します。インラインの <svg> に加え、CSS の @keyframes/CDN から読み込む GSAP を使った <script>/SMIL の <animate*> のいずれかを含めます。制御方法は 1 つだけ選んでください。
  • スクリーンショット用に任意の時点でアニメーションを停止できるよう、選んだ制御方法に対応するシークハーネスを含めます。

シークハーネス — 正確な時点で停止する。 ?t=N で指定の時点へ移動して一時停止し、スクリーンショットで静止フレームを撮影できるようにします。SVG のアニメーション方法に合った仕組みを使用してください。

<script>
  const t = new URLSearchParams(location.search).get("t");
  if (t !== null) {
    const N = parseFloat(t);
    // SMIL: pause the SVG's own clock and scrub it
    const svg = document.querySelector("svg");
    svg.pauseAnimations(); svg.setCurrentTime(N);
    // CSS @keyframes draw-on: el.style.animationDelay=(-N)+"s"; el.style.animationPlayState="paused";
    // GSAP timeline: tl.pause(); tl.seek(N);
  }
  window.__ready = true;
</script>

検証ループ — レンダリング → 停止 → スクリーンショット → 確認: ファイルを開始/中間/終了時点(?t=0、?t=<dur/2>、?t=<dur>)で開き、それぞれスクリーンショットを撮影して、忠実度(ストロークが正しい方向に描画されるか、モーフィングの端点がきれいか)とアーティファクト(パスが viewBox でクリップされていないか、古い dashoffset によってストロークが消えていないか、FOUC、モーフィングの継ぎ目でのカクつき)を確認します。ヘッドレスツールはどれでも使用できます。

npx playwright screenshot --wait-for-timeout=500 "file://$PWD/icon.html?t=0.7" frame-mid.png

完了前の確認事項:

  1. スタンドアロンで開けること。コンソールエラーがなく、インライン SVG にアクセスでき、CDN(使用している場合)が読み込まれること。
  2. 選んだ制御方法のシーク機能で、決定論的なフレームを停止できること。
  3. 開始/中間/終了時点のスクリーンショットを撮影し、要件に合致していること。クリッピングや viewBox 外へのストロークがないこと。
  4. prefers-reduced-motion に対応していること。ループや大きな動きが制限され、静止した最終状態が維持されること。
  5. イージングが意図的に選ばれていること。ease/GSAP のイージングを目的に沿って選び、意図しない linear の描画アニメーションがないこと。

参考ファイル

  • references/svg-techniques.md — dashoffset の計算方法と getTotalLength の注意点、pathLength="1" による正規化、GSAP MorphSVG と Flubber の選択ガイド(コード付き)、アイコン切り替えのモーフィング(ハンバーガー ↔ 閉じる)、MotionPath/offset-path の詳細、SMIL・CSS・JS の比較、およびアニメーション向けに調整した SVGO 設定をまとめています。

コメント