日記

日本語の勉強のためのブログ

【JavaScript】canvasに入力画像を描画する

もともと別の記事に書いていた内容だが、読みづらいと感じたため分割。

1. 画像の読み込み

まず画像を読み込む方法について学んだ。
HTMLに

<input type="file" id="input_image" accept="image/*">

を設置することで、ファイル選択ボタンが表示される(ここではaccept="image/*"と設定しているため、画像のみ選択できるようになっている)。
画像が選択された際にイベントを発生させるには

const input_image = document.getElementById("input_image");
input_image.addEventListener("change", () => {
    /* ここに処理を書く */
});

とすればよい。

2. canvasに画像を表示

※理解できていない部分も多いので、誤りがあったら申し訳ない。

大まかな流れを書くと、

  1. 選択されたファイルをFileReaderでData URLに変換し、
  2. Data URLを画像(HTMLImageElement)として読み込み、
  3. 画像をcanvasに描画する

という流れで、canvasに画像を表示することになる。

順を追って説明する。

2.1 ファイルをFileReaderでData URLに変換

まず、選択されたファイルをFileReader.readAsDataURL()に渡し、Data URLという形式に変換する。
変換が終わる前に次のステップに進むわけにはいかないので、変換完了まで待機し、それを確認してから次の動作(Data URLを画像として読み込み~)を行う必要がある。
そこで用いるのがFileReader.onloadである。ここに、変換終了後に実行する内容(関数)を代入する。

// FileReaderオブジェクトの生成
const reader = new FileReader();

input_image.addEventListener("change", () => {
    // 選択されたファイル (File型)
    let file = input_image.files[0];
    // そのファイルをData URLとして読み込む
    reader.readAsDataURL(file);

    // Fileを読み込み終わった後の動作
    reader.onload = () => {
        /* 2.2で追記 */
    }
});

2.2 Data URLを画像として読み込む

次に、得たData URLからImageオブジェクトを生成する。つまり、Data URLを画像として読み込むことになる。
FileReaderと同様、画像読み込みが完了してから次の動作を行う必要があるため、Image.onloadを用いている。
以下のコードは、2.1のコードで/* 2.2で追記 */と書かれた部分に入るコードである。

// HTMLImageElementを新規作成
let image = new Image();

// Data URLをimageに渡す(画像として読み込む)
image.src = reader.result;

// 画像(image)を読み込み終わった後の動作
image.onload = () => {
    /* 2.3で追記 */
}

2.3 画像をcanvasに描画する

ここまで来たら簡単である。canvasのサイズを画像サイズと等しくなるように変更したのち、drawImage()で描画すればよい。
以下のコードは、2.2のコードで/* 2.3で追記 */と書かれた部分に入るコードである。

// canvasのサイズを画像に合うよう変更
canvas.width = image.width;
canvas.height = image.height;
// canvasに画像を描画
ctx.drawImage(image, 0, 0);

2.4 以上の全体像

2.1 ~ 2.3をまとめたコードを以下に示す。

// FileReaderオブジェクトの生成
const reader = new FileReader();

input_image.addEventListener("change", () => {
    // 選択されたファイル (File型)
    let file = input_image.files[0];
    // そのファイルをData URLとして読み込む
    reader.readAsDataURL(file);

    // Fileを読み込み終わった後の動作
    reader.onload = () => {
        // HTMLImageElementを新規作成
        let image = new Image();

        // Data URLをimageに渡す(画像として読み込む)
        image.src = reader.result;

        // 画像(image)を読み込み終わった後の動作
        image.onload = () => {
            // canvasのサイズを画像に合うよう変更
            canvas.width = image.width;
            canvas.height = image.height;
            // canvasに画像を描画
            ctx.drawImage(image, 0, 0);
        }
    }
});

参考文献