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 ym dx dy移動(描画なし)Move To
L x yl dx dy直線 Line To
H xh dx水平線
V yv dy垂直線
C x1 y1 x2 y2 x yc ...3 次ベジェ曲線
S x2 y2 x ys ...3 次ベジェ(前回の制御点を反射)
Q x1 y1 x yq ...2 次ベジェ
T x yt ...2 次ベジェ(反射)
A rx ry rot large sweep x ya ...楕円弧
Zz閉じる 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
   ↓  ↓  ↓                ↓         ↓     ↓
   楕円の半径            「大弧?」「時計回り?」終点

例: 円の半分

<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(穴あき)

<!-- ドーナツ -->
<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 変換は機械的:

path のリファクタ

Path → CSS clip-path

SVG の path を CSS の clip-path: path(...) に転用可能(モダンブラウザ)。 DOM 要素を非矩形にクリップ。

失敗パターン

症状対処
図形が反転しているY は下向きを忘れる
弧が変な向きlarge / sweep フラグの組み合わせ
閉じないZ を忘れる、または最後を始点に
意図しない直線Q / C の制御点ミス
JS で生成した path が壊れるカンマ / スペース / 数値精度
file が大きいSVGO で最適化、不要小数削減
学び方

path は文字を見るだけでは難しい。実際にエディタで描いて確認するのが一番速い。 SVG Path Editorsvg-path-visualizer.netlify.app が便利。