web-dev-qa-db-ja.com

JavaScript / jQueryを使用して画像をプリロードする決定的な最良の方法は?

この質問はどこでも、on SOとoffの両方で尋ねられ、答えられたことを完全に承知しています。しかし、毎回異なる答えがあるようです。たとえば、 this =、 this および that

JQueryを使用しているかどうかは気にしません。重要なのは、それが機能し、クロスブラウザであることです。]

それでは、画像をプリロードする最良の方法は何ですか?

50
Skilldrick

残念ながら、それはあなたの目的に依存します。スタイルの目的で画像を使用する場合、最善の策はスプライトを使用することです。 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];
  }
}
_

JavaScriptで複数の画像をプリロードする最良の方法は何ですか? )から取得した変更されたソース

new Image()を使用すると、DOMメソッドを使用する費用はかかりませんが、指定されたイメージの新しいリクエストがキューに追加されます。この時点で画像は実際にはページに追加されていないため、再レンダリングは行われません。ただし、ページの最後にこれを追加して(可能な場合はすべてのスクリプトがそうであるように)、より重要な要素を保持しないようにすることをお勧めします。

編集:コメントを反映するように編集され、適切に機能するには別個のImageオブジェクトが必要であることを非常に正確に指摘しています。ありがとう.

Edit2:再利用性をより明確にするために編集

Edit 3(3年後):

ブラウザが非表示画像を処理する方法が変更されたため(display:none、またはこの回答のようにドキュメントに追加されない)、プリロードへの新しいアプローチが推奨されます。

Ajaxリクエストを使用して、画像の早期取得を強制できます。たとえば、jQueryを使用します。

_jQuery.get(source);
_

または、前の例のコンテキストでは、次のことができます。

_function preload(sources)
{
  jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
_

これはそのままのスプライトの場合には適用されないことに注意してください。これは、写真ギャラリーやスライダー/カルーセルなど、画像が最初は表示されないために読み込まれない画像用のものです。

また、このメソッドはIEに対して機能しないことに注意してください(ajaxは通常、画像データの取得には使用されません)。

65

スプリッティング

他の人が述べたように、スプリッティングはさまざまな理由で非常にうまく機能しますが、それは意図されたほど良くありません。

  • 逆に、画像に対してHTTPリクエストを1つだけ作成することになります。しかし、YMMV。
  • 欠点は、すべてを1つのHTTPリクエストでロードすることです。現在のほとんどのブラウザは2つの同時接続に制限されているため、画像リクエストは他のリクエストをブロックできます。したがって、YMMVおよびメニューの背景のようなものは少しレンダリングされない場合があります。
  • 複数の画像が同じカラーパレットを共有しているため、ある程度の節約がありますが、常にそうであるとは限らず、無視できるほどです。
  • 画像間で共有されるデータが増えるため、圧縮が改善されます。

しかし、不規則な形状を扱うのは難しいです。すべての新しい画像を新しい画像に結合することは、別の迷惑です。

<img>タグを使用したロージャックアプローチ

most definitiveのソリューションを探している場合は、私が今でも好むロージャックアプローチを採用する必要があります。ドキュメントの最後に画像への<img>リンクを作成し、widthおよびheightを1x1ピクセルに設定し、さらに非表示のdivに配置します。ページの最後にある場合、他のコンテンツの後に読み込まれます。

14
aleemb

2013年1月の時点で、ここで説明した方法はどれも役に立たなかったため、代わりにChrome 25およびFirefox 18を使用してテストし、動作しました。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になりますので、注意してください。

6
Mahn

私の意見では、いくつかのライブラリで導入されたMultipart XMLHttpRequestを使用することは、今後数年間で推奨されるソリューションになるでしょう。ただしIE <v8、まだdata:uriをサポートしていません(IE8でもサポートは制限されており、最大32 kbが許可されています)。並列イメージプリロードの実装は次のとおりです- http: //code.google.com/p/core-framework/wiki/ImagePreloading 、フレームワークにバンドルされていますが、まだ見る価値があります。

3
Angel

これは昔からでしたので、私はまだ何人が画像のプリロードに興味を持っているのかわかりません。

私の解決策はさらにシンプルでした。

CSSを使用しました。

#hidden_preload {
    height: 1px;
    left: -20000px;
    position: absolute;
    top: -20000px;
    width: 1px;
}
1
Scott Cleland

私のユースケースでは、プリロードしたいフルスクリーン画像のカルーセルがありました。ただし、画像は順番に表示され、読み込みに数秒かかることがあるため、順番に順番に読み込むことが重要です。

これには、非同期ライブラリの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を渡します。

0
DanH

ここでは、画像が読み込まれた後にフェードインする簡単なソリューションを紹介します。

    function preloadImage(_imgUrl, _container){
        var image = new Image();
            image.src = _imgUrl;
            image.onload = function(){
                $(_container).fadeTo(500, 1);
            };
        }
0
Afonso Praça