私は、この質問がSOのオンとオフの両方でどこでも尋ねられ、回答されていることを十分に認識しています。しかし、毎回、this、this、thatなど、異なる答えがあるようです。
jQuery を使用しているかどうかは気にしません。重要なのは、それが機能し、クロスブラウザーであることです。]
では、画像をプリロードする最良の方法は何ですか?
残念ながら、それはあなたの目的によって異なります。スタイルのために画像を使用する場合は、スプライトを使用することをお勧めします。 http://www.alistapart.com/articles/sprites2
ただし、 <img> タグで画像を使用する予定がある場合は、それらを事前にロードする必要があります
function preload(sources)
{
var images = [];
for (i = 0, length = sources.length; i < length; ++i) {
images[i] = new Image();
images[i].src = sources[i];
}
}
( What is the best way to preload multiple images in JavaScript?から取得した修正ソース)
DOM メソッドを使用new Image()
する費用はかかりませんが、指定された画像に対する新しいリクエストがキューに追加されます。この時点では、画像は実際にはページに追加されていないため、再レンダリングは必要ありません。ただし、これをページの最後に追加することをお勧めします (可能であれば、すべてのスクリプトがそうであるように)。
Image
編集:適切に機能するには別のオブジェクトが必要であることを指摘するコメントを正確に反映するように編集されました。ありがとう、そしてそれをもっと詳しくチェックしなかったのは私の悪いことです。
Edit2:再利用性をより明確にするために編集
編集 3 (3 年後):
ブラウザーが非表示の画像を処理する方法が変更されたため (display:none または、この回答のようにドキュメントに追加されない)、プリロードへの新しいアプローチが推奨されます。
Ajax リクエストを使用して、画像の早期取得を強制できます。たとえば、jQuery を使用すると、次のようになります。
jQuery.get(source);
または、前の例のコンテキストでは、次のことができます。
function preload(sources)
{
jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
これは、そのままで問題ないスプライトの場合には当てはまらないことに注意してください。これは、最初は表示されていないために画像が読み込まれない、フォト ギャラリーや画像を含むスライダー/カルーセルなどのためのものです。
また、この方法は IE では機能しないことに注意してください (通常、画像データの取得に ajax は使用されません)。
スプリッティング
他の人が述べたように、スプライトはさまざまな理由で非常にうまく機能しますが、意図したほど良くはありません.
ただし、不規則な形状を処理するのは難しいです。すべての新しい画像を新しい画像に結合することは、もう 1 つの煩わしさです。
<img> タグを使用したロー ジャック アプローチ
最も決定的な解決策を探している場合は、私がまだ好むロージャック アプローチを使用する必要があります。ドキュメントの最後に画像への <img> リンクを作成し、width
andheight
を 1x1 ピクセルに設定し、さらに非表示の div に配置します。ページの最後にある場合は、他のコンテンツの後に読み込まれます。
2013年1月の時点で、ここで説明する方法はどれもうまくいきませんでした。代わりに、Chrome25とFirefox18でテストして動作させました。jQueryとこのプラグインを使用して、読み込みイベントの癖を回避します。
function preload(sources, callback) {
if(sources.length) {
var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);
$.each(sources, function(i,source) {
$("<img/>").attr("src", source).appendTo(preloaderDiv);
if(i == (sources.length-1)) {
$(preloaderDiv).imagesLoaded(function() {
$(this).remove();
if(callback) callback();
});
}
});
} else {
if(callback) callback();
}
}
使用法:
preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() {
console.log("done");
});
キャッシュが無効になっていると、結果がまちまちになることに注意してください。キャッシュが無効になっていると、開発者ツールが開いているときにChromeでデフォルトになります。そのため、この点に注意してください。
私の意見では、一部のライブラリで導入された Multipart XMLHttpRequest を使用することが、今後数年間で推奨されるソリューションになるでしょう。ただし、IE < v8 では、まだ data:uri をサポートしていません (IE8 でさえサポートが制限されており、最大 32kb まで許可されています)。これは並列画像プリロードの実装です - http://code.google.com/p/core-framework/wiki/ImagePreloading、フレームワークにバンドルされていますが、一見の価値があります。
これはかなり前のことなので、今でも画像のプリロードに興味を持っている人がどれだけいるかはわかりません。
私の解決策はさらに単純でした。
私はちょうどCSSを使用しました。
#hidden_preload {
height: 1px;
left: -20000px;
position: absolute;
top: -20000px;
width: 1px;
}
私のユースケースでは、プリロードしたい全画面画像のカルーセルがありました。ただし、画像は順番に表示され、それぞれの読み込みに数秒かかる場合があるため、順番に順番に読み込むことが重要です。
これには、非同期ライブラリのwaterfall()
メソッド ( https://github.com/caolan/async#waterfall )を使用しました。
// Preload all images in the carousel in order.
image_preload_array = [];
$('div.carousel-image').each(function(){
var url = $(this).data('image-url');
image_preload_array.push(function(callback) {
var $img = $('<img/>')
$img.load(function() {
callback(null);
})[0].src = url;
});
});
async.waterfall(image_preload_array);
callback()
これは、関数の配列を作成することで機能します。各関数には、配列内の次の関数を呼び出すために実行する必要があるパラメーターが渡されます。の最初のパラメーターcallback()
はエラー メッセージで、null 以外の値が指定された場合にシーケンスを終了するため、毎回 null を渡します。
ロード後に画像をフェードインする簡単なソリューションを次に示します。
function preloadImage(_imgUrl, _container){
var image = new Image();
image.src = _imgUrl;
image.onload = function(){
$(_container).fadeTo(500, 1);
};
}