SVG の基礎と活用法 - ベクター画像の仕組みからアニメーションまで
SVG とは - ラスター画像との根本的な違い
SVG (Scalable Vector Graphics) は、XML ベースのベクター画像フォーマットです。JPEG や PNG などのラスター画像がピクセルの集合で画像を表現するのに対し、SVG は数学的な図形 (点、線、曲線、多角形) の記述で画像を定義します。この根本的な違いにより、SVG はどれだけ拡大しても画質が劣化しないという特性を持ちます。
SVG とラスター画像の比較:
- 解像度非依存: SVG はベクターデータのため、Retina ディスプレイや 4K モニターでも常に鮮明に表示されます。ラスター画像は拡大するとピクセルが見えてぼやけますが、SVG にはこの問題がありません
- ファイルサイズ: シンプルな図形 (アイコン、ロゴ、図表) では SVG の方が圧倒的に小さくなります。一方、写真のような複雑な画像では SVG は不向きで、ラスター画像の方が効率的です
- 編集可能性: SVG はテキストエディタで直接編集できる XML です。CSS でスタイルを変更したり、JavaScript で動的に操作したりできます。ラスター画像はピクセルデータのため、このような柔軟な操作ができません
- アクセシビリティ: SVG 内のテキストは検索エンジンやスクリーンリーダーが読み取れます。
<title>や<desc>要素で説明を追加でき、アクセシブルな画像を作成できます
SVG が適している用途: アイコン、ロゴ、図表、グラフ、地図、UI 要素、イラスト、アニメーション。SVG が不向きな用途: 写真、複雑なテクスチャ、グラデーションが多い自然画像。用途に応じてラスター画像と使い分けることが重要です。
SVG の基本構造 - 座標系と主要要素
SVG ファイルは XML 形式で記述され、<svg> ルート要素の中に図形要素を配置する構造です。座標系の理解が SVG を扱う上での基礎となります。
基本的な SVG の構造:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
<circle cx="50" cy="50" r="40" fill="#3498db" />
</svg>
viewBox 属性は SVG 内部の座標系を定義します。viewBox="0 0 100 100" は、左上が (0,0)、右下が (100,100) の座標空間を意味します。width と height は実際の表示サイズです。viewBox と表示サイズが異なる場合、SVG は自動的にスケーリングされます。
主要な図形要素:
- <rect>: 矩形。
<rect x="10" y="10" width="80" height="60" rx="5" />で角丸矩形を描画 - <circle>: 円。
<circle cx="50" cy="50" r="30" />で中心 (50,50)、半径 30 の円 - <ellipse>: 楕円。
<ellipse cx="50" cy="50" rx="40" ry="25" /> - <line>: 直線。
<line x1="0" y1="0" x2="100" y2="100" stroke="black" /> - <polyline>: 折れ線。
<polyline points="0,0 50,80 100,0" /> - <polygon>: 多角形。
<polygon points="50,0 100,100 0,100" />で三角形 - <path>: パス。最も強力な要素で、あらゆる形状を描画可能
- <text>: テキスト。
<text x="50" y="50" text-anchor="middle">Hello</text>
<g> 要素でグループ化し、transform 属性で移動・回転・拡大縮小を適用できます。<defs> 要素内に再利用可能な定義を配置し、<use> 要素で参照する設計パターンも重要です。
SVG パスの書き方 - d 属性のコマンド体系
<path> 要素の d 属性は、SVG で最も強力かつ複雑な機能です。一連のコマンドで任意の形状を描画でき、アイコンフォントやイラストの大部分はパスで構成されています。
主要なパスコマンド:
- M (moveto): ペンを移動。
M 10 20で座標 (10, 20) に移動 - L (lineto): 直線を描画。
L 50 80で現在位置から (50, 80) まで直線 - H (horizontal lineto): 水平線。
H 90で x=90 まで水平に描画 - V (vertical lineto): 垂直線。
V 60で y=60 まで垂直に描画 - C (curveto): 3 次ベジェ曲線。
C x1 y1, x2 y2, x yで 2 つの制御点と終点を指定 - S (smooth curveto): 滑らかな 3 次ベジェ曲線。前のコマンドの制御点を反転して使用
- Q (quadratic curveto): 2 次ベジェ曲線。
Q cx cy, x yで 1 つの制御点と終点 - A (arc): 楕円弧。
A rx ry rotation large-arc sweep x y - Z (closepath): パスを閉じる。始点まで直線で接続
大文字コマンドは絶対座標、小文字コマンドは相対座標 (現在位置からの差分) を使用します。例えば l 10 20 は「現在位置から右に 10、下に 20」の意味です。
実践的なパスの例 (チェックマークアイコン):
<path d="M 20 50 L 40 70 L 80 30" fill="none" stroke="green" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
複雑なパスを手書きすることは稀で、通常は Figma、Illustrator、Inkscape などのベクターエディタで作成し、SVG としてエクスポートします。エクスポート後に SVGO で最適化することで、不要なメタデータや冗長な記述を削除し、ファイルサイズを削減します。
CSS と JavaScript による SVG の操作 - 動的なスタイリングとインタラクション
SVG を HTML にインラインで埋め込むことで、CSS と JavaScript から SVG の各要素を自由に操作できます。これにより、ホバーエフェクト、テーマ切り替え、データに基づく動的な描画など、インタラクティブなグラフィックスが実現します。
CSS による SVG スタイリング:
svg .icon-path {
fill: #333;
transition: fill 0.3s ease;
}
svg:hover .icon-path {
fill: #e74c3c;
}
SVG 固有の CSS プロパティ:
fill: 塗りつぶし色。currentColorを使えば親要素のcolorを継承stroke: 線の色stroke-width: 線の太さstroke-dasharray: 破線パターン。アニメーションと組み合わせて「描画される」効果を実現stroke-dashoffset: 破線の開始位置。stroke-dasharrayと組み合わせてパス描画アニメーションopacity: 透明度transform: 変形 (SVG の transform は CSS transform と同じ構文)
JavaScript での操作例:
const path = document.querySelector('.chart-bar');
path.setAttribute('d', `M 0 100 L 0 ${100 - value} L 20 ${100 - value} L 20 100 Z`);
データ可視化では、D3.js や Chart.js が SVG を動的に生成してグラフを描画します。SVG の DOM 操作は HTML と同じ API (querySelector、setAttribute、addEventListener) で行えるため、Web 開発者にとって学習コストが低いのが利点です。
SVG アニメーション - SMIL と CSS アニメーションの使い分け
SVG アニメーションには、SMIL (SVG 固有のアニメーション記法)、CSS アニメーション、JavaScript (Web Animations API / GSAP) の 3 つの方法があります。それぞれに得意分野があり、用途に応じて使い分けます。
CSS アニメーション (推奨):
最も一般的で、Web 開発者に馴染みのある方法です。@keyframes と animation プロパティで SVG 要素をアニメーションさせます。GPU アクセラレーションが効く transform と opacity を中心に使用すると、60fps の滑らかなアニメーションが実現します。
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loading-icon { animation: spin 1s linear infinite; }
SMIL アニメーション:
SVG 内に直接記述するアニメーションで、<animate>、<animateTransform>、<animateMotion> 要素を使用します。パスに沿った移動 (animateMotion) など、CSS では実現困難なアニメーションが可能です。ただし、Chrome が一時期 SMIL の廃止を検討した経緯があり、新規実装では CSS や JavaScript を優先することが推奨されます。
JavaScript アニメーション (GSAP / Web Animations API):
複雑なタイムライン制御、スクロール連動、ユーザー操作に応じた動的アニメーションには JavaScript が最適です。GSAP (GreenSock Animation Platform) は SVG アニメーションのデファクトスタンダードで、モーフィング (形状変化)、パス描画、スタガーアニメーションなど高度な表現が可能です。
パフォーマンスの観点では、アニメーションする要素数が多い場合 (100 要素以上)、SVG よりも Canvas の方が高速です。SVG は DOM ベースのため、要素数に比例して描画コストが増加します。
SVG の最適化とパフォーマンス - 実務での注意点
SVG ファイルはテキストベースのため、不要なメタデータや冗長な記述が含まれがちです。最適化により、ファイルサイズを 30-70% 削減できる場合があります。特にアイコンセットのように多数の SVG を使用するサイトでは、最適化の効果が累積して大きなパフォーマンス改善につながります。
SVGO (SVG Optimizer) による最適化:
- 不要なメタデータの削除: エディタが挿入するコメント、名前空間宣言、非表示レイヤーなどを削除
- 座標の丸め:
M 10.123456 20.789012をM 10.12 20.79に丸めてファイルサイズを削減。精度はfloatPrecisionパラメータで制御 - パスの最適化: 冗長なコマンドの統合、相対座標への変換、不要な空白の削除
- 属性の短縮:
fill="#ffffff"をfill="#fff"に短縮
インライン SVG vs 外部ファイルの判断基準:
- インライン SVG: CSS/JS で操作する必要がある場合、HTTP リクエストを減らしたい場合、小さなアイコン (1KB 以下) の場合に適しています
- 外部ファイル (
<img>/background-image): ブラウザキャッシュを活用したい場合、同じ SVG を複数ページで使用する場合、CSS/JS での操作が不要な場合に適しています - SVG スプライト: 複数のアイコンを 1 つの SVG ファイルにまとめ、
<use href="#icon-name">で参照する方式。HTTP リクエスト数を削減しつつ、キャッシュも活用できます
パフォーマンス上の注意点として、複雑なフィルタ (<feGaussianBlur>、<feDropShadow>) は描画コストが高いため、多用を避けます。特にモバイルデバイスでは、フィルタ付き SVG がスクロールのカクつきの原因になることがあります。