写真を clip() で切り抜いた後、別の描画まで欠けることがあります。クリッピング領域は次の描画にも残るためです。
一時的な切り抜きでは、clip() の前に save() を呼び、描画が終わったら restore() で状態を戻します。新しいクリッピング領域は、それまでの領域との共通部分になります。大きな四角形で再度 clip() しても、狭くなった範囲を広げることはできません。
次の例は、読み込み済みの画像と新しい 2D コンテキストを受け取る想定です。座標変換や既存のクリップがない状態で、左上の 120 × 120 の範囲に画像を表示します。
function drawClippedImage(ctx, image) {
ctx.save();
try {
ctx.beginPath();
ctx.rect(0, 0, 120, 120);
ctx.clip();
ctx.drawImage(image, 0, 0);
} finally {
ctx.restore();
ctx.beginPath();
}
ctx.fillText("Preview", 140, 30);
}
finally に入れておくと、描画中に例外が発生しても保存した状態を戻せます。ただし例外自体は呼び出し元へ伝わります。
現在のパスは save() と restore() の保存対象ではありません。そのため例では、切り抜き用のパスを作る前と、一時処理を終えた後に beginPath() を呼んでいます。
この関数は画像を拡大縮小しません。中央を切り抜く場合や枠全体を写真で埋める場合は、drawImage() の元画像側の範囲と出力先の範囲を別に計算してください。