JavaScriptのCanvas APIのdrawImage()メソッドを使い、キャンバスに画像を描画する方法を解説します。

下準備

まずは下準備から。htmlの<body></body>内に以下のcanvas要素を配置します。

<canvas id="canvas"></canvas>

jsにてコンテキストを取得します。

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas

キャンバスの範囲がわかりやすいようにcssにて背景色を設定してあります。

canvas {
  background: skyblue;
}

drawImage()メソッドでキャンバスに画像を描画

まずは描画に使う画像をimgフォルダに追加します。

上のgreen.pngというファイル名の画像を使っていきます。サイズは80 x 80ピクセルです。

次に、画像をhtmlに追加します。

  <div class="assets">
    <img id="green" src="img/green.png">
  </div>

img要素で追加し、jsから取得しやすいようにid名をgreenに設定します。描画用のimg要素は画面に表示させないため、class名をassetsに指定したdiv要素に格納し、cssで非表示にします。

.assets {
  display: none;
}

あとはjsに以下のコードを追加するとキャンバスに画像が描画されます。

const green = document.getElementById('green');
ctx.drawImage(green, 0, 0);

drawImage()メソッドを使うと、キャンバスに画像を描画することができます。引数の取り方は3パターン存在し、上記は最もシンプルな形となります。drawImage(image, dx, dy)の形式で、imageにはimg要素、dxとdyは描画位置を座標で指定します。キャンバスの左上を原点(0, 0)とし、指定した座標を左上として画像を描画します。

画像を拡大、縮小して描画

引数を2つ追加することで、拡大、縮小することができます。

ctx.drawImage(green, 0, 0, 40, 40);

drawImage(image, dx, dy, dWidth, dHeight)の形式で、dWidthに幅、dHeightに高さを指定します。幅と高さに半分の40を指定したため、半分のサイズに縮小されたのがわかります。

画像の一部を描画

さらに引数を4つ追加することで、画像の一部を描画することができます。

上のcolors.pngというファイル名の画像をimgフォルダに追加します。サイズは160 x 80ピクセルです。

htmlの.assetsの中に以下のimg要素を追加します。

<img id="colors" src="img/colors.png">

jsを以下のように変更すると、キャンバスに緑の図形だけが描画されます。

const colors = document.getElementById('colors');
ctx.drawImage(colors, 0, 0, 80, 80, 0, 0, 80, 80);

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)の形式で、sxとsyで描画元の画像の実際に描画する矩形領域の左上の座標を指定し、dWidthとdHeightでその幅と高さを指定します。

以下のようにsxを80ずらすことでピンクの図形を描画することができます。

ctx.drawImage(colors, 80, 0, 80, 80, 0, 0, 80, 80);

画像読み込み後に描画

これまでに紹介した方法だと、drawImage()のタイミングで指定した画像の読み込みが完了していない場合、何も描画されません。画像のキャッシュ状態、画像のサイズ、PCの処理速度など、何かしらの条件により画像の読み込みが遅延し、描画に失敗する場合があります。

以下のようにすることで画像の読み込み完了を待って描画することができます。

const green = document.getElementById('green');

if (green.complete) {
  draw();
} else {
  green.addEventListener('load', draw);
}

function draw() {
  ctx.drawImage(green, 0, 0);
}

img要素のcompleteプロパティを調べると、画像の読み込みが完了している場合trueを、未完了の場合falseを返します。読み込み済みの場合はそのまま描画処理をし、読み込みが完了していない場合はaddEventListenerのloadイベントにて、画像の読み込み完了後に描画処理が実行されるようにイベントリスナを追加します。

jsにて画像読み込み

別の方法として、drawImage()で描画する画像をjsにて読み込む方法があります。

この方法ではhtmlにimg要素を追加する必要がないため、.assetsと中のimg要素はすべて削除します。その上でjsを以下のようにすると、jsだけで画像の読み込みから描画まで行うことができます。

const img = new Image();
img.addEventListener('load', () => {
  ctx.drawImage(img, 0, 0);
});
img.src = 'img/green.png';

まずはImage()コンストラクタを使い、img要素を生成します。new Image()とすると、img要素を生成して返すので、定数imgに格納します。

次に、imgのsrcプロパティに描画用の画像ファイルのパスを指定します。

あとはdrawImage()の描画元画像にimgを指定しますが、画像の読み込み完了を待つ必要があるため、srcプロパティを指定する前にimgにloadイベントを追加し、中に描画処理を書きます。