やりたいこと
ローカルの画像ファイルをHTMLのCanvasに表示します。
検索するといくつか引っかかるのですが、試してみたところ動作しませんでした。
(エラーなどは出力されずCanvasになにも表示されませんでした。)
環境
Chrome:131.0.6778.86
試したコード
HTML
<input type="file" id="file" accept="image/png, image/jpeg"></div>
<canvas id="canvas"></canvas>
JavaScript
document.getElementById("file").onchange = (event) => {
const file = event.target.files[0];
if(!file.type.match(/^image\/(png|jpeg)$/)) return ;
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.src = reader.result;
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0);
}
reader.readAsDataURL(file);
}
ファイルが選択された際にImageを作成してsrcに選択された画像を入れています。
作成された画像をCanvasにdrawImageで描画しています。正しそうに見えますが、自分の環境では動作しませんでした。
対策
JavaScript側を以下のように修正することで動作しました。
imgのsrcを設定後にimgを操作するコードをsetTimeoutを呼ぶことで、いったんIdle状態にしたあとに行うようにしています。
document.getElementById("file").onchange = (event) => {
const file = event.target.files[0];
if(!file.type.match(/^image\/(png|jpeg|gif)$/)) return ;
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.src = reader.result;
setTimeout( ()=> {
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0);
});
}
reader.readAsDataURL(file);
}
余談
自分の環境では修正前のcanvas.width = img.width;が呼ばれるタイミングでimg.widthの値が0でした。そのためimgが正しい状態になっていないと考えsetTimeoutを呼ぶようにしました。
余談2
修正前とほぼ同じコードをサンドボックスで動作させているサイトでは動作していました。
何か別の要因があるのかもしれません。(自分のコードが悪いのかタイミング問題なのか)
結果
ローカルの画像ファイルをCanvasに表示することができました。
コメント