SVG アニメーション

CSS / JS / SMIL の 3 流派。線を描く / 形を変える / モーフィング / モーションパス / Lottie まで。

3 つの流派

方式特徴
CSS Animationシンプル / GPU 加速 / 推奨
JS(rAF / WAAPI / GSAP / motion)動的・制御強
SMIL(<animate> 等)標準 / 一部非推奨気味

詳細な自作トゥイーン / イージングは Tween セクション

CSS Animation で動かす

<svg viewBox="0 0 100 100">
  <circle class="bouncer" cx="50" cy="50" r="20" fill="orange" />
</svg>

<style>
  .bouncer {
    transform-origin: center;
    animation: bounce 1s ease-in-out infinite alternate;
  }
  @keyframes bounce {
    from { transform: translateY(0); }
    to   { transform: translateY(-30px); }
  }
</style>

線を描くアニメーション(stroke-dash)

<svg viewBox="0 0 100 100">
  <path d="M10,50 Q50,10 90,50" fill="none" stroke="black" stroke-width="2" />
</svg>
<style>
  path {
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    animation: draw 2s ease forwards;
  }
  @keyframes draw { to { stroke-dashoffset: 0; } }
</style>

事前にパス長を計測するか、pathLength="100" で正規化:

<path pathLength="100" stroke-dasharray="100" stroke-dashoffset="100" />

モーションパス(要素を path に沿って動かす)

.dot {
  offset-path: path("M 10 50 Q 50 0 90 50");
  offset-distance: 0%;
  offset-rotate: auto;
  animation: travel 3s linear infinite;
}
@keyframes travel { to { offset-distance: 100%; } }

SMIL(<animate> 系)

SVG 標準のアニメ。Chrome / Safari は対応、IE は元々非対応。 簡単な動きには十分。

<circle cx="50" cy="50" r="20" fill="orange">
  <animate
    attributeName="r"
    from="20" to="40"
    dur="1s"
    repeatCount="indefinite" />
</circle>

主な要素

animateTransform の例

<rect width="20" height="20">
  <animateTransform
    attributeName="transform"
    type="rotate"
    from="0 50 50"
    to="360 50 50"
    dur="2s"
    repeatCount="indefinite" />
</rect>

animateMotion

<circle r="5" fill="red">
  <animateMotion dur="3s" repeatCount="indefinite">
    <mpath href="#trail" />
  </animateMotion>
</circle>
<path id="trail" d="M0 50 Q 50 0 100 50" fill="none" />

SMIL はChrome が一時的に廃止予告 → 撤回の経緯あり。新規プロジェクトでは CSS or JS が無難

WAAPI(Web Animations API)

const circle = document.querySelector("circle")

circle.animate(
  [
    { transform: "translateY(0)" },
    { transform: "translateY(-30px)" },
    { transform: "translateY(0)" },
  ],
  { duration: 1000, iterations: Infinity, easing: "ease-in-out" }
)

JS で属性を直接動かす

const circle = document.querySelector("circle")
let r = 20
let dir = 1

function tick() {
  r += dir * 0.5
  if (r > 30 || r < 20) dir *= -1
  circle.setAttribute("r", r)
  requestAnimationFrame(tick)
}
tick()

詳細は Tween セクション

モーフィング(path の d を変える)

2 つの path 間を補間する。点の数が同じなら CSS / JS で補間できる:

.shape {
  d: path("M 10 10 H 90 V 90 H 10 Z");
  transition: d 0.5s ease;
}
.shape:hover {
  d: path("M 50 10 L 90 90 L 10 90 Z");
}

対応ブラウザはまだ限定。実用はGSAP MorphSVG / Flubber などが定番。

ライブラリ

Lottie

After Effects で作ったアニメーションを JSON にして再生。 CPU / GPU で軽く、複雑な演出も可。

<script src="https://cdn.jsdelivr.net/npm/lottie-web"></script>
<div id="anim"></div>
<script>
  lottie.loadAnimation({
    container: document.getElementById("anim"),
    path: "data.json",
    loop: true, autoplay: true,
  })
</script>

dotLottie(.lottie)はバイナリ + 圧縮で軽量化された後継。

typical アニメーション集

1. ローダーリング

<svg viewBox="0 0 50 50" width="40">
  <circle cx="25" cy="25" r="20" fill="none" stroke="orange" stroke-width="4"
    stroke-dasharray="80 40" />
</svg>
<style>
  circle { animation: spin 1s linear infinite; transform-origin: center; }
  @keyframes spin { to { transform: rotate(360deg); } }
</style>

2. チェックマーク

<svg viewBox="0 0 24 24" stroke="green" stroke-width="3" fill="none">
  <path d="M5 12 l5 5 l9 -10" pathLength="100"
    stroke-dasharray="100" stroke-dashoffset="100">
    <animate attributeName="stroke-dashoffset" from="100" to="0" dur="0.4s" fill="freeze" />
  </path>
</svg>

3. ハンバーガー → ✕

.bar { transition: transform 0.3s, opacity 0.3s; transform-origin: center; }
.open .bar1 { transform: translateY(8px) rotate(45deg); }
.open .bar2 { opacity: 0; }
.open .bar3 { transform: translateY(-8px) rotate(-45deg); }

4. 進捗バー

<rect x="0" y="0" width="100%" height="4" fill="#eee" />
<rect class="bar" x="0" y="0" width="0" height="4" fill="orange" />
<style>
  .bar { transition: width 0.3s ease; }
</style>

Reduce Motion 対応

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; }
}

パフォーマンス

失敗パターン

症状対処
線描画が動かないstroke-dasharray と offset を必ずセット
回転中心がズレるtransform-origin: center / rotate(angle, cx, cy)
SMIL がブラウザで動かないCSS / WAAPI に書き換え
カクつく属性アニメ → CSS transform へ
モーフが崩れる点数を揃える / Flubber などの補間ライブラリ
使い分け

シンプルな動き → CSS。複雑な演出 → GSAP / motion。 AE 由来の凝ったアニメ → Lottie / Rive。状態を持つアニメ → Rive