path 完全解説
SVG の最強要素 <path d="...">。すべての図形を表現できるペン制御コマンド。
M / L / H / V / C / S / Q / T / A / Z を一通り。
path とは
ペンを「移動・描画・閉じる」コマンドで操作する。 d 属性に文字列で書く:
<path d="M 10 10 L 90 10 L 90 90 L 10 90 Z" fill="orange" />
コマンド一覧
| 大文字 | 小文字 | 意味 |
|---|---|---|
| M x y | m dx dy | 移動(描画なし)Move To |
| L x y | l dx dy | 直線 Line To |
| H x | h dx | 水平線 |
| V y | v dy | 垂直線 |
| C x1 y1 x2 y2 x y | c ... | 3 次ベジェ曲線 |
| S x2 y2 x y | s ... | 3 次ベジェ(前回の制御点を反射) |
| Q x1 y1 x y | q ... | 2 次ベジェ |
| T x y | t ... | 2 次ベジェ(反射) |
| A rx ry rot large sweep x y | a ... | 楕円弧 |
| Z | z | 閉じる Close Path |
大文字 = 絶対座標、小文字 = 相対座標(直前の終点からの差分)。
M (Move To)
M 10 10 ← (10, 10) にペンを移動
m 5 5 ← 直前から (+5, +5)
最初は必ず M で始まる。複数の M でサブパスを作れる(穴あきや複数図形)。
L (Line To)
M 10 10 L 90 10 L 90 90 L 10 90 Z
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
起点 水平 垂直 水平 閉じる
H, V(直交線の短縮)
M 10 10 H 90 V 90 H 10 Z
= M 10 10 L 90 10 L 90 90 L 10 90 Z
3 次ベジェ C
最も柔軟な曲線。2 つの制御点 + 終点で指定:
M x0 y0
C cx1 cy1, cx2 cy2, x y
(x0, y0) ●─ ─ ─ ●(cx1, cy1)
curve...
●(cx2, cy2)
╲
●(x, y)
<path d="M 20 80 C 40 10, 70 10, 90 80" fill="none" stroke="black" />
滑らかにつなぐ S
前の制御点を反射して滑らかに連結:
M 10 50
C 20 10, 40 10, 50 50
S 80 90, 90 50
2 次ベジェ Q / T
制御点 1 つ + 終点で指定。シンプルな曲線。
M 10 80 Q 50 10, 90 80
T で滑らかに
前の制御点を反射する 2 次ベジェ:
楕円弧 A(最強かつ最難)
A rx ry x-axis-rotation large-arc sweep x y
↓ ↓ ↓ ↓ ↓ ↓
楕円の半径 「大弧?」「時計回り?」終点
- rx, ry: 楕円の半径
- x-axis-rotation: 楕円の傾き(度)
- large-arc-flag: 0 = 短い弧、1 = 長い弧
- sweep-flag: 0 = 反時計回り、1 = 時計回り
- x, y: 終点
例: 円の半分
<path d="M 10 50 A 40 40 0 0 1 90 50" fill="none" stroke="black" />
4 つのパターン
large=0 sweep=0 → 短い弧、反時計
large=0 sweep=1 → 短い弧、時計 ← 一番直感
large=1 sweep=0 → 長い弧、反時計
large=1 sweep=1 → 長い弧、時計
円グラフセクター
function arcPath(cx, cy, r, startAngle, endAngle) {
const startX = cx + r * Math.cos(startAngle)
const startY = cy + r * Math.sin(startAngle)
const endX = cx + r * Math.cos(endAngle)
const endY = cy + r * Math.sin(endAngle)
const large = endAngle - startAngle > Math.PI ? 1 : 0
return `M ${cx} ${cy} L ${startX} ${startY} A ${r} ${r} 0 ${large} 1 ${endX} ${endY} Z`
}
Z(Close Path)
最後の点と最初の点を直線で結ぶ。図形を閉じる。
サブパス
<!-- 2 つの長方形を 1 つの path で -->
<path d="M 0 0 H 50 V 50 H 0 Z M 60 0 H 100 V 50 H 60 Z" fill="orange" />
fill-rule(穴あき)
- nonzero(既定)— 巻き数で判定
- evenodd — 奇数回横切れば内側
<!-- ドーナツ -->
<path d="M 0 0 h 100 v 100 h -100 z M 30 30 h 40 v 40 h -40 z"
fill-rule="evenodd" fill="orange" />
区切り文字
コマンドと数値、数値と数値の間は空白またはカンマ。混在 OK。
M10,10 L90,10L90,90 z
M 10 10 L 90 10 L 90 90 z
連続コマンドの省略
M 10 10 L 20 20 L 30 30 L 40 40
↓ 同じコマンドが続けば省略可
M 10 10 L 20 20 30 30 40 40
JS で path を生成
function rectPath(x, y, w, h) {
return `M ${x} ${y} h ${w} v ${h} h ${-w} z`
}
function smoothLine(points) {
if (points.length === 0) return ""
let d = `M ${points[0].x} ${points[0].y}`
for (let i = 1; i < points.length; i++) {
d += ` L ${points[i].x} ${points[i].y}`
}
return d
}
長さの取得
const path = document.querySelector("path")
const total = path.getTotalLength()
const point = path.getPointAtLength(total * 0.5)
console.log(point.x, point.y)
これを使えばパスに沿って動かすアニメーションが書ける(→ アニメ)。
線描画アニメーション(stroke-dash トリック)
<path d="..." stroke="black" fill="none"
stroke-dasharray="100" stroke-dashoffset="100">
</path>
@keyframes draw {
to { stroke-dashoffset: 0; }
}
path { animation: draw 2s ease forwards; }
典型 path レシピ
角丸長方形(rx を使わず)
M 10,0 H 90 a 10,10 0 0 1 10,10 V 50 a 10,10 0 0 1 -10,10 H 10 a 10,10 0 0 1 -10,-10 V 10 a 10,10 0 0 1 10,-10 z
ハート
M 50,30
C 50,15, 30,15, 30,30
C 30,45, 50,55, 50,70
C 50,55, 70,45, 70,30
C 70,15, 50,15, 50,30 z
葉っぱ
M 10 50 Q 50 0 90 50 Q 50 100 10 50 z
波線
M 0 50 q 25 -25 50 0 t 50 0 t 50 0 t 50 0
path から基本図形へ
基本図形 → path 変換は機械的:
- circle(cx,cy,r) →
M cx-r,cy a r,r 0 1,0 2r,0 a r,r 0 1,0 -2r,0 - rect(x,y,w,h) →
M x,y h w v h h -w z
path のリファクタ
- SVGOMG / SVGO で不要小数を削減
- 同じコマンドの連続を省略
- 相対座標化で短く
Path → CSS clip-path
SVG の path を CSS の clip-path: path(...) に転用可能(モダンブラウザ)。
DOM 要素を非矩形にクリップ。
失敗パターン
| 症状 | 対処 |
|---|---|
| 図形が反転している | Y は下向きを忘れる |
| 弧が変な向き | large / sweep フラグの組み合わせ |
| 閉じない | Z を忘れる、または最後を始点に |
| 意図しない直線 | Q / C の制御点ミス |
| JS で生成した path が壊れる | カンマ / スペース / 数値精度 |
| file が大きい | SVGO で最適化、不要小数削減 |
path は文字を見るだけでは難しい。実際にエディタで描いて確認するのが一番速い。 SVG Path Editor や svg-path-visualizer.netlify.app が便利。