(先制攻撃:これを重複としてマークしたい場合は、他の質問で「なぜこのエラーが発生するのですか?」と尋ねられることに注意してください。なぜこのエラーが発生するのかわかります。 JavaScriptコードのエラーを検出できます。これはFirebugコンソールにのみ表示され、もちろん、画像が読み込まれたときにユーザーにわかります。)
レスポンシブ画像には picturefill を使用しています。画像のloadイベントに対して発生するコールバックがあります。そのため、誰かがブラウザウィンドウのサイズを変更するたびにコールバックが実行され、picturefillを介して別の画像が読み込まれます。
コールバック内で、キャンバスを介して画像データをdataURLに変換しているので、画像データをlocalStorageにキャッシュして、オフラインのときでもユーザーが利用できるようにしています。
「オフライン」に関する部分に注意してください。そのため、ブラウザのキャッシュに頼ることができません。また、HTML5オフラインアプリケーションキャッシュは、画像が応答するため、私のニーズを満たしていません。 (レスポンシブイメージとHTMLオフラインアプリケーションキャッシュの非互換性の説明については、 「アプリケーションキャッシュはDouchebagです」 を参照してください。)
MacのFirefox14.0.1では、ブラウザのサイズを非常に大きいものに変更してから、大きい画像が完全に読み込まれる前にもう一度小さいものにサイズを変更すると、読み込み画像が起動します。 Firebugコンソールで「画像が破損または切り捨てられました」と報告されることになりますが、例外をスローしたり、エラーイベントをトリガーしたりすることはありません。コードに問題があることを示すものはありません。 Firebugコンソールだけで。その間、切り捨てられた画像をlocalStorageに保存します。
JavaScript内でこの問題を確実かつ効率的に検出して、その画像をキャッシュしないようにするにはどうすればよいですか?
これが、picturefill divをループして、picturefillによって挿入されたimgタグを見つける方法です。
_ var errorLogger = function () {
window.console.log('Error loading image.');
this.removeEventListener('load', cacheImage, false);
};
for( var i = 0, il = ps.length; i < il; i++ ){
if( ps[ i ].getAttribute( "data-picture" ) !== null ){
image = ps[ i ].getElementsByTagName( "img" )[0];
if (image) {
if ((imageSrc = image.getAttribute("src")) !== null) {
if (imageSrc.substr(0,5) !== "data:") {
image.addEventListener("load", cacheImage, false);
image.addEventListener('error', errorLogger, false);
}
}
}
}
}
_
そして、cacheImage()
コールバックは次のようになります。
_var cacheImage = function () {
var canvas,
ctx,
imageSrc;
imageSrc = this.getAttribute("src");
if ((pf_index.hasOwnProperty('pf_s_' + imageSrc)) ||
(imageSrc.substr(0,5) === "data:") ||
(imageSrc === null) || (imageSrc.length === 0)) {
return;
}
canvas = w.document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
try {
dataUri = canvas.toDataURL();
} catch (e) {
// TODO: Improve error handling here. For now, if canvas.toDataURL()
// throws an exception, don't cache the image and move on.
return;
}
// Do not cache if the resulting cache item will take more than 128Kb.
if (dataUri.length > 131072) {
return;
}
pf_index["pf_s_"+imageSrc] = 1;
try {
localStorage.setItem("pf_s_"+imageSrc, dataUri);
localStorage.setItem("pf_index", JSON.stringify(pf_index));
} catch (e) {
// Caching failed. Remove item from index object so next cached item
// doesn't wrongly indicate this item was successfully cached.
delete pf_index["pf_s_"+imageSrc];
}
};
_
最後に、有罪を保護するためにURLが変更されたFirebugで見たものの全文を次に示します。
画像が破損または切り捨てられました: http://www.example.com/pf/external/imgs/extralarge.png
src
タグのimg
属性を変更すると、Firefoxはload
イベントを発生させるようです。これは、src属性が変更された場合、すでに進行中の他のフェッチを終了する必要があり(Firefoxが行う)、イベントが発生しないというHTML5仕様 は とは反対です。送信されます。 load
イベントは、フェッチが正常に完了した場合にのみ送信する必要があります。したがって、load
イベントを取得するという事実はFirefoxのバグだと思います。
ただし、画像はそれが完全に利用可能かどうかを知っている必要があります、complete
属性を使用してみてください。
if (this.complete === false) {
return;
}
残念ながら、Firefoxでは代わりにthis.complete
がtrue
に設定されているため、これもオプションではありません。
最良のオプションは、src
属性を変更するたびに新しい<img>
要素を作成することです。
今日、私はこの問題に唖然としました。 Firefoxエラーコンソールにエラーが表示され続けることを除いて、すべてが正常に機能していました(画像は期待どおりに読み込まれました)-IEまたはChrome 。
私の場合、完全なjqueryハンドラーでinnerHtmlを使用して画像をdivにプラグインしていました。次のコマンドでjquery呼び出しをプリエンプションすると、エラーが停止しました。
var image_holder = new Image();
image_holder.src = img_path;//path of image that's going to be plugged in
それは私にとってはうまくいきましたが、それでも意味がありません。このコードは、実際に画像をページに接続するコードに到達する前に画像の読み込みを開始するため、タイミングと関係があると思います。