Image.onloadを同期で読み込む
Javascriptの画像の読み込みなどは非同期で実行されます。コードの途中でimage.srcで画像を設定しても一連のプログラムが完了した後に画像ファイルが読み込まれます。今回はその回避方法をご紹介します。
非同期を巧みに利用する
タイトルは同期で読み込むと書いてありますが、実際は非同期で読み込みます。問題の本質は同期ではなく、プログラムが連続して実行すればいいだけのはずです。
「同期ができないできないぞ、Javascriptってなんだこれ!」と私のように必死に検索している方は、お茶などで一服した後に考えると実は簡単に同期もどきはできるのです。
あなたの作業時間がなくなりますので、さくっとコードを記載しますね。
同期の代用プログラム
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <canvas id="MyCanvas"></canvas> <script> // グローバル変数 var GIF_Base64 =[ "data:image/gif;base64,R0lGODlhDAAMAIEAAJnZ6vDw8P///////yH5BAAAAAAALAAAAAAMAAwAAAgxAAEIHCigoMGBBA0WRChQ4UKGASIehCjxIcKIARwKwMgQgEGODD9G7KiRpEOTCjsGBAA7", "data:image/gif;base64,R0lGODlhEgASAIEAAJnZ6vDw8P///////yH5BAAAAAAALAAAAAASABIAAAhLAAEIHDhQgMGDBwkqRMhQIUGGCB0WhGhQosAAGAM0tJhRY0SOGTdK7CjSIUmKAjoGsAgAoUqWLjvCPPjSIkoBMynmhLiz5EKULAMCADs=", "data:image/gif;base64,R0lGODlhIAAgAIEAAJnZ6vDw8P///////yH5BAAAAAAALAAAAAAgACAAAAiGAAEIHEiwIAABCBMqXCjAoMOBDCMmfPhQokSKDi1GxGhQI0OOBT0uBElQpEKSAwOoXBnAIkqBLFe6fBlT5UyUNVtepFnzJsmcPkEC3YmzJ9GfRk0KyKny5UGGTAM4jRh1KlSmVhdWfUkVK9erObOaFCuSrEezGtEG5agUodqjINs2/KrUaUAAOw=="]; var GIF_Image = new Array(); var GIF_Image_Count = 0; for(i = 0; i < GIF_Base64.length; i++){ GIF_Image[GIF_Image.length] = new Image(); GIF_Image[GIF_Image.length-1].onload = function() { GIF_Image_Count++; // 全ての画像が読み終えたらイベントを発動 if(GIF_Image_Count == GIF_Base64.length){ OnImageLoaded(); } } // イメージにBase64形式のPNGを設定する GIF_Image[GIF_Image.length-1].src = GIF_Base64[i]; } function OnImageLoaded(){ // キャンバスの取得 var canvas = document.getElementById("MyCanvas"); canvas.width = 500; canvas.height = 500; if (canvas.getContext) { // コンテキストの取得 var ctx = canvas.getContext("2d"); // キャンバスに画像を描画 var max_height = 0; for(i = 0; i < GIF_Base64.length; i++){ ctx.drawImage(GIF_Image[i],0,max_height); max_height += GIF_Image[i].height+30; } } } </script> </body> </html>
コードの解説
プログラムの流れとしては、グローバル変数を3つ用意します。「画像データ、Imageオブジェクト用の配列、カウンタ」です。 画像データはHTMLのロード時に読み込まれないようにBase64で定義しています。
19行目から33行目はImageオブジェクトを作成して、onloadイベント、srcプロパティを設定します。コメントにあるように全ての画像が読み終えたらイベントを発動させます。
35行目から53行目は読み込んだ画像をcanvasに描画しているだけです。このOnImageLoaded()の中にお好きな処理を記述する形となります。
実行結果
12x12、18x18、32x32の画像が上から順に描画されます。
以上となります。
関連記事
画像をBase64に変換してHTMLやCSSに埋め込む[リクエスト数の軽減]