「ブラウザで画像を先読みしたい、簡単な方法はないか?」と聞かれたら、
(new Image()).src = URL;
がお勧めです。
この一行で、ブラウザに画像をキャッシュさせる事ができます。
ただ、ブラウザに任せっきりではなく、細かくハンドリングしたい場合もあります。
このエントリはそのような場合に、どういった情報が利用できるかのメモです。
まずはブラウザ毎の挙動を知りましょう。
http://zoo.uupaa.net/issues/image/load.error/ で試せます。
function imageLoader(url) {
var img = new Image();
img.onabort = function() { _dump("abort", img); };
img.onerror = function() { _dump("error", img); };
img.onload = function() { _dump("load", img); };
img.src = url;
}
function _dump(eventType, img) {
console.group();
console.log(eventType === "load" ? "SUCCESS" : "ERROR");
console.log("img.src = " + img.src);
console.log("img.complete = " + img.complete);
console.log("img.naturalHeight = " + img.naturalHeight);
console.log("img.naturalWidth = " + img.naturalWidth);
console.log("img.width = " + img.width);
console.log("img.height = " + img.height);
console.groupEnd();
}
imageLoader("http://example.com/missing.jpg" + "?t=" + Date.now()); // cache busting
imageLoader("http://gyazo.com/f9e2c42f334f6ce9ce45d5e025602937.png" + "?t=" + Date.now());
imageLoader("http://gyazo.com/f9e2c42f334f6ce9ce45d5e025602937.png");
imageLoader("http://gyazo.com/f9e2c42f334f6ce9ce45d5e025602937.png");
存在しないファイル example.com/missing.jpg を読み込んだ場合はこうなります。
Property | IE 6,7,8 | IE 9,10,11 | Chrome | Safari | Firefox |
---|---|---|---|---|---|
eventType | "error" | "error" | "error" | "error" | "error" |
complete | false | false | true | true | true |
naturalWidth | undefined | 0 | 0 | 0 | 0 |
width | 28 | 28 (IE 11 は 0) | 0 | 0 | 0 |
height | 30 | 30 (IE 11 は 0) | 0 | 0 | 0 |
width: 28, height: 30 という謎の数字は、IE で画像読み込み失敗時に表示される [×]
アイコンのサイズ分です。
存在するファイル gyazo.com/f9e2c42f334f6ce9ce45d5e025602937.png を読み込んだ場合はこうなります。
IE 6,7,8,9,10 は IE 11 のエミュレーションで確認しています。
Property | IE 6,7,8 | IE 9,10,11 | Chrome | Safari | Firefox |
---|---|---|---|---|---|
eventType | "load" | "load" | "load" | "load" | "load" |
complete | false (※) | true | true | true | true |
naturalWidth | undefined | 1007 | 1007 | 1007 | 1007 |
width | 1007 | 1007 | 1007 | 1007 | 1007 |
height | 669 | 669 | 669 | 669 | 669 |
(iOS, Android の挙動は中の人が暇になった時に追加する予定ですが、基本的にSafariと同じはずです)
※: IE 11 のエミュレーションだと false ですが、 2008年に IE6,7 を実機調査した時は true でした
画像の読み込み完了と失敗をハンドリングするには、以下のコードで対応できそうです。
if (img.naturalWidth || eventType === "load") {
// 読み込み成功
} else {
// 読み込み失敗
}
シンプルですね。
昔はこのへんの挙動は本当にバラバラでしたが、5年の歳月を経て統一されてきています。 良い感じですね。