
【JavaScript入門】パスの描画
ブラウザ Canvas の「パス描画」は、複数の点を結んで図形を作り、その 内側を塗りつぶす か 輪郭に沿って線を引く ベクター形式の描画手法です。ラスター形式(1 px 単位で色を塗る)に比べ、拡大・回転しても劣化せず、複雑な形を少ない命令で表現できます。ここではパスを組み立てるメソッドと、塗り・線・クリップの 3 大レンダリング操作を段階的に学びます。

1.パスを構築するメソッド
メソッド | 役割 |
---|---|
beginPath() | 既存パスをリセットし、新しいパスの定義を開始する。 |
moveTo(x, y) | 始点を設定し、サブパスを開始する。 |
lineTo(x, y) | 指定座標へ直線パスを追加する。 |
closePath() | 始点と終点を結びパスを閉じる。 |

1.1. サブパスと複数図形
moveTo()
を使えば 1 つの beginPath()
で複数図形を定義できます。サブパスごとに moveTo
→ lineTo…
を繰り返し、最後にまとめて塗り / 線を適用すると高速です。
1.2. 開いたパスと閉じたパス
closePath()
を呼ばないと「開いた図形」になります。塗りつぶす場合は自動的に線を結んで面を作りますが、線描画時は結ばれません。
1.3. 曲線パス(発展)
Bezier 曲線 quadraticCurveTo / bezierCurveTo
や扇形の arc
などでスムーズなカーブも追加できます。ここでは概要に留め、詳細は次章で扱います。
2.パスを描画・加工するメソッド
メソッド | 役割 |
---|---|
fill() | パス内部を現在の fillStyle で塗る。 |
stroke() | パス輪郭を strokeStyle と lineWidth で描く。 |
clip() | 現在のパスを「切り抜きマスク」にする(以降の描画を制限) |
2.1. 塗り (fill
)
パスが閉じているかどうかに関わらず、内部を塗ります。非ゼロ/偶数–奇数ルールも指定可能ですが既定では非ゼロです。
2.2. 線 (stroke
)
lineWidth
, lineCap
, lineJoin
を組み合わせてデザインを調整します。線幅はパス中心基準で内外に等しく広がる点に注意。
2.3. クリップ (clip
)
clip()
実行後の描画は、パスの内側だけに現れます。save()
で状態を退避し、不要になったら restore()
で元に戻すのが定石です。
2.4. 高速化のヒント
- 設定変更 (
fillStyle
,strokeStyle
など) はバッチごとにまとめる。 - 一連の図形を 1 回の
beginPath()
→ 描画で完結させる。 - アニメーション時は
clearRect
または差分描画で最小限の更新範囲に抑える。
3.パスの描画:サンプルプログラム
ファイル名: path_demo.html
PNGファイルのダウンロードは、ここ「checker.png」からできます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>🖌️ Canvas Path Demo</title>
<style>
body{font-family:"Segoe UI",sans-serif;background:#f4f9ff;text-align:center;margin:2rem}
h1 {font-size:1.8rem;margin-bottom:1rem}
canvas{border:1px solid #666;border-radius:6px;background:url(./checker.png)}
#msg{margin-top:.8rem;color:#004d40;font-weight:bold}
</style>
</head>
<body>
<h1>🖌️ パスの描画デモ</h1>
<canvas id="stage" width="420" height="260"></canvas>
<p id="msg">パスを使って三角形を描きました!</p>
<script>
(() => {
const cvs = document.getElementById('stage');
const ctx = cvs.getContext('2d');
/* 共通スタイル */
ctx.fillStyle = '#ffb3c1'; // 塗り色
ctx.strokeStyle = '#3559e0'; // 線色
ctx.lineWidth = 10;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
/* パス開始 */
ctx.beginPath();
/* 左の三角(閉じない)*/
ctx.moveTo(70,50);
ctx.lineTo(30,210);
ctx.lineTo(150,210);
/* 右の三角(閉じる)*/
ctx.moveTo(260,50);
ctx.lineTo(180,210);
ctx.lineTo(340,210);
ctx.closePath(); // 右のみ閉じる
ctx.fill(); // 両方塗りつぶし
ctx.stroke(); // 輪郭を描画
})();
</script>
</body>
</html>
ブラウザの出力例

- ピンク色で塗りつぶされた大小 2 つの三角形
- 左は頂点間の上辺が描かれず、線は 2 辺のみ
- 右は 3 辺すべて輪郭があり、頂点が丸く仕上がる
- 下部に “パスを使って三角形を描きました!” と日本語メッセージ
プログラム解説
行 | 内容 | 解説 |
---|---|---|
16–18 | strokeStyle , lineWidth , lineCap , lineJoin | 線端と角を丸くすることで見栄えを向上 |
23 | beginPath() | 既存パスの消去+新規定義開始 |
26–28 | 左三角の 3 頂点を moveTo /lineTo で指定 | closePath を呼ばないため開いた図形 |
31–34 | 右三角を定義し closePath() で頂点結合 | ここでのみパスを閉じる。 |
36–37 | fill() → stroke() の順 | 塗りを先に行うと線が最前面に来て見やすい。 |
4.クリップ領域

4.1. クリップ領域の概要
クリップ領域を設定すると、その領域内だけに描画が制限されます。領域外への描画はマスクされ、見えなくなります。
4.2. 主なメソッド
メソッド | 説明 |
---|---|
ctx.save() | 現在の描画状態(変形行列・クリップ領域・スタイルなど)をスタックに保存 |
ctx.clip() | 直前に定義したパスをクリップ領域として設定 |
ctx.restore() | スタックから保存した描画状態を復元し、クリップ領域も元に戻す。 |
5.クリップ領域:サンプルプログラム
ファイル名: clip_region.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>🎯 clip_region.html</title>
<style>
body { font-family:"Segoe UI",sans-serif; background:#f0f8ff; margin:2rem }
h1 { text-align:center; font-size:1.8rem; margin-bottom:1rem }
canvas { display:block; margin:0 auto; background:#fff; border:1px solid #ccc }
</style>
</head>
<body>
<h1>🎯 クリップ領域の利用</h1>
<canvas id="canvas" width="400" height="300"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// 背景を描画
ctx.fillStyle = "#eee";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// クリップ前の状態を保存
ctx.save();
// クリップ領域を定義
ctx.beginPath();
ctx.rect(100, 50, 200, 150);
ctx.clip();
// クリップ領域内に円を描画
ctx.fillStyle = "steelblue";
ctx.beginPath();
ctx.arc(200, 125, 100, 0, Math.PI * 2);
ctx.fill();
// 状態を復元しクリップを解除
ctx.restore();
// クリップ領域を視覚化する枠を描画
ctx.strokeStyle = "tomato";
ctx.lineWidth = 3;
ctx.strokeRect(100, 50, 200, 150);
</script>
</body>
</html>
ブラウザの出力例
キャンバス中央にある赤枠(100×50 〜 300×200 の矩形)内にだけ青い円が描画され、それ以外は背景色だけが見える。

プログラム解説
ctx.save()
:現在のクリップ領域を含む描画状態を保存。ctx.rect()
→ctx.clip()
:矩形パスをクリップ領域として設定し、以降の描画をその内側だけに制限。ctx.arc()
・ctx.fill()
:円を描画するが、クリップ領域外は自動的にマスクされる。ctx.restore()
:保存しておいた描画状態を復元し、クリップ領域を解除。ctx.strokeRect()
:クリップ領域を赤い枠で可視化。
これで、.save()
/.clip()
/.restore()
を組み合わせて、必要な領域だけに描画を行う方法が理解できました。
まとめ
- パスは
beginPath
→ 点列定義 →fill
/stroke
の 3 ステップ。 - 1 つの
beginPath()
に複数サブパスを入れると、描画回数を減らして性能向上。 clip()
を組み合わせればマスク表現も可能。
これらを応用すると、チャートライブラリの折れ線やゲームのキャラクター当たり判定など、あらゆるベクター描画に展開できます。まずは図形を自由に組み合わせ、パス操作に慣れてみましょう。