0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

destination-in で写真を円形に切り抜く最小例

0
Posted at

Canvas 2D で写真を円形に切り抜く例です。写真を先に描き、destination-in に切り替えてから円を描きます。既存の写真は円と重なる範囲に残り、外側は透明になります。

この例では入力をデコード済みの正方形画像に限定します。写真を正方形へ切り出す処理は含めません。長方形の写真をそのまま引き伸ばすと縦横比が変わるので、必要なら先に切り出す範囲を決めてください。

新しい canvas に画像を描いた後、合成モードを保存・変更します。円の色は黒でも、写真を黒く塗る用途ではありません。ここでは円の不透明な範囲をマスクに使っています。restore() 後は後続の描画に destination-in が残りません。

書き出した PNG は、白以外の背景にも重ねて確認します。白いプレビューだけでは、角が透明になったか判断しにくいためです。CSS で丸く見せるだけの場合と違い、この処理は書き出す画像自体の角を透明にします。

入力には同一オリジンの画像や、適切に CORS を設定して読み込んだ画像など、canvas の読み出しが許される素材を使います。合成処理が見た目どおりでも、書き出しが許可される条件まで変わるわけではありません。

円の縁には半透明のピクセルが含まれ得ます。透明を維持したい用途では PNG など対応する出力形式を選び、実際の配置先でも確認します。

function circularPhoto(image, size) {
  if (image.naturalWidth <= 0 ||
      image.naturalWidth !== image.naturalHeight ||
      !Number.isInteger(size) || size <= 0) {
    throw new Error("A decoded square image and positive size are required");
  }
  const canvas = document.createElement("canvas");
  canvas.width = canvas.height = size;
  const ctx = canvas.getContext("2d");
  if (!ctx) throw new Error("2D canvas unavailable");
  ctx.drawImage(image, 0, 0, size, size);
  ctx.save();
  ctx.globalCompositeOperation = "destination-in";
  ctx.beginPath();
  ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
  ctx.fill();
  ctx.restore();
  return canvas;
}

参考: MDN globalCompositeOperation

筆者は HEIC 変換プロジェクト Morphio に関わっています。画像の入出力を扱う際の実装メモとして書きました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?