- JavaScript 内での画像をロードしたい。
- 間違った理解で解説してるサイトが結構あるようなので騙されないようにしましょう。
ごく簡単なロード手順
JavaScript で画像をロードするのはとても簡単。
// 画像オブジェクトの新規生成
var image = new Image();
// ロード完了まで表示できないので、終了後に表示開始するように組む
image.onload =
function() {
// ロード完了時処理
};
// 必須ではないけどエラー時の処理も設定できる。エラー時には onload は
// 呼ばれないので、これがないとロード中のまま先に進まなくなる。
image.onerror =
function() {
// ロードエラー時処理
};
// ロードする画像を設定。この設定によって非同期でロードが開始される
image.src = "画像URL";
ちょっと面倒なのは、画像のロード処理は非同期で、ロード完了するまでは表示できないので、必ずイベントリスナーでロード完了待ちする作りにしないといけない事くらい。
どうしてこじらせちゃったのかな?
で、画像のロードについてネットで調べてると、結構な率で「IEにはバグがあって、onload
の処理が呼ばれない事がある」というページが見つかる。おまけにそれを回避するための泥臭い対処コードまで載ってたりしてやる気を著しく削がれるのだけれど、実はそれは勘違いで、そもそもそんな対策をする必要はないらしい。
その手のページの方々のサンプルを見ると、src
プロパティに URL を設定した後に onload
を設定してるようで、それだと 画像がキャッシュに乗ってる場合などは onload
を設定する前に非同期ロード処理が完了してしまう事もあり、その場合は当然 onload
も呼ばれない、というだけの事らしい。最初に見つけたページがまさにそれで危うく真に受ける所だったけど、一応他も調べてみてよかったよ。
ちなみに個人的な愚痴としては、プロパティのセッタで高負荷な事をやりたがるのって利用者には罠にしかならないからキライなんだよね。ガッツリ処理する事はメソッドにしてほしい。
new Image()
って何なんだよ
ついでに画像周りでもうひとつひっかかった点。画像を読み込む際に、
var image = new Image();
って感じでオブジェクトを作るんだけど、僕は TypeScript で組んでるし、プロパティの型はちゃんと書きたい派なので、
public image: Image;
とか書いてみたら 「Image なんてオブジェクトは無え!」 と怒られた。で、そのあと調べて実体は HTMLImageElement
だという事が分かったので、じゃあ紛らわしいからいっそ、
// プロパティ宣言
public image: HTMLImageElement;
// 初期化時
image = new HTMLImageElement();
とか書いてみたら今度は 「その操作はサポートされていない!」 とか怒られて、
いったいお前は何なんだよ!
とキレそうになりましたが、結局まだちゃんと調べてはいないんだけど、どうも HTMLElement
の仲間たちは、
// 'img' で生成すれば HTMLImageElement が作られる。
document.createElement( 'タグ名' );
という方法でしか作る事ができないようで、それをいちいち書くのが面倒だから new Image(); だけで作れるようにした、という感じなのかな?。画像のロードや管理のために html の img タグを作って使うという発想はなかった。
DOM の事はあまりよく勉強しないまま canvas だけでモノを作ろうとしてるから基本的な常識がないんですよな。盛大な勘違いをしてたらまた後で訂正します。