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>
主な要素
- <animate> — 数値属性を変化
- <animateTransform> — transform 系
- <animateMotion> — パスに沿って
- <set> — 値を即セット
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 などが定番。
ライブラリ
- GSAP — SVG 親和性最強。MorphSVG / DrawSVG プラグイン
- motion — 軽量・モダン
- anime.js — シンプル
- Velocity.js — 古典
- Lottie — After Effects → JSON
- Rive — インタラクティブ・状態遷移
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; }
}
パフォーマンス
- CSS の
transform / opacityは GPU 加速 - SVG 属性のアニメ(cx, r 等)は CPU で再描画 → 重め
- filter は毎フレームコスト大、軽く扱う
- 大量要素のアニメはCanvas / WebGL を検討
失敗パターン
| 症状 | 対処 |
|---|---|
| 線描画が動かない | stroke-dasharray と offset を必ずセット |
| 回転中心がズレる | transform-origin: center / rotate(angle, cx, cy) |
| SMIL がブラウザで動かない | CSS / WAAPI に書き換え |
| カクつく | 属性アニメ → CSS transform へ |
| モーフが崩れる | 点数を揃える / Flubber などの補間ライブラリ |
使い分け
シンプルな動き → CSS。複雑な演出 → GSAP / motion。 AE 由来の凝ったアニメ → Lottie / Rive。状態を持つアニメ → Rive。