jQueryで画像をプリロードする


689

JavaScriptで画像をプリロードするための迅速で簡単な方法を探しています。それが重要な場合は、jQueryを使用しています。

私はこれをここで見ました(http://nettuts.com ...):

function complexLoad(config, fileNames) {
  for (var x = 0; x < fileNames.length; x++) {
    $("<img>").attr({
      id: fileNames[x],
      src: config.imgDir + fileNames[x] + config.imgFormat,
      title: "The " + fileNames[x] + " nebula"
    }).appendTo("#" + config.imgContainer).css({ display: "none" });
  }
};

しかし、それは私が欲しいものに対して少しオーバーザックに見えます!

これを行うjQueryプラグインが世の中にあることは知っていますが、それらはすべて(サイズが)少し大きいようです。画像をプリロードするための迅速、簡単、かつ短い方法が必要です!


10
$.each(arguments,function(){(new Image).src=this});
デビッドヘルシング

回答:


969

クイック簡単に:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        $('<img/>')[0].src = this;
        // Alternatively you could use:
        // (new Image()).src = this;
    });
}

// Usage:

preload([
    'img/imageName.jpg',
    'img/anotherOne.jpg',
    'img/blahblahblah.jpg'
]);

または、jQueryプラグインが必要な場合:

$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}

// Usage:

$(['img1.jpg','img2.jpg','img3.jpg']).preload();

25
ブラウザが確実にキャッシュするために、画像要素をDOMに挿入する必要はありませんか?
JoshNaro、2010

8
$('<img />')メモリ内に画像要素を作成するだけだと思います(リンクを参照)。'$('<img src="' + this + '" />')より「複雑」なため、実際には非表示のDIV内に要素を作成するように見えます。ただし、これはほとんどのブラウザに必要だとは思いません。
JoshNaro、2011

104
これは、jQueryプラグインを作成する奇妙な方法です。なんで$.preload(['img1.jpg', 'img2.jpg'])
アレックス

12
$(window).load(function(){/*preload here*/});ドキュメント内のすべての画像が最初に読み込まれるので、最初に必要になる可能性が高いので、必ずこれを内部で呼び出してください。
Jasper Kennis

12
@RegionalC- ロードイベントが設定される前にイメージのロードが終了した場合に備えて、load設定する前にイベントを設定する方が少し安全かもしれませんsrc$('<img/>').load(function() { /* it's loaded! */ }).attr('src', this);
スペアバイト

102

以下は、実際に画像をDOMにロードしてデフォルトで非表示にする最初の応答の微調整バージョンです。

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img />').attr('src',this).appendTo('body').css('display','none');
    });
}

38
hide()はより簡潔ですcss('display', 'none')
アレックス、2011

6
それらをDOMに挿入する利点は何ですか?
アレックス

それらをDOMに挿入する利点についても知りたいです。
jedmao 2013

11
私の経験から、画像をDOMにプリロードすると、ブラウザはその存在を認識し、適切にキャッシュされるようになります。それ以外の場合、画像はメモリにのみ存在し、単一ページのアプリでのみ機能します。
Dennis Rongo 2013

デニスロンゴ。DOMに画像を追加すると、Chromeでランダムに再読み込みされる問題が修正されました。ありがとう!
tmorell 2013年

52

JavaScript 画像オブジェクトを使用します

この関数を使用すると、すべての画像のロード時にコールバックをトリガーできます。ただし、少なくとも1つのリソースがロードされていない場合、コールバックはトリガーされないことに注意してください。これは、onerrorコールバックを実装してloaded値をインクリメントするか、エラーを処理することで簡単に修正できます。

var preloadPictures = function(pictureUrls, callback) {
    var i,
        j,
        loaded = 0;

    for (i = 0, j = pictureUrls.length; i < j; i++) {
        (function (img, src) {
            img.onload = function () {                               
                if (++loaded == pictureUrls.length && callback) {
                    callback();
                }
            };

            // Use the following callback methods to debug
            // in case of an unexpected behavior.
            img.onerror = function () {};
            img.onabort = function () {};

            img.src = src;
        } (new Image(), pictureUrls[i]));
    }
};

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('a');
});

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('b');
});

4
JavaScriptイメージオブジェクトを使用して、正しいことを行います。これらの回答で人々が間違ったことをしているのを見ましか?
アレックス、2013年

華麗なコード。onload画像がキャッシュされていても、これがイベントを発生させると私は思っていますか?(img.onloadが最初に宣言されているため)。これは私のテストが示したものです。
Startec 2014年

3
@alex可能性があります。事前ロードすることが目的の場合(これはパフォーマンスの順序を示唆しています)、jQueryに依存するオプションではなく、未加工のJSオプションを使用することをお勧めします。
チャーリーシュリーサー2014

このソリューションは気に入りましたが、Firefoxで機能しないことがわかりました。それは私だけですか、それとも他の人にも同じ問題がありますか?
Gazillion

@Gazillionが詳細を説明します。「機能しない」とはどのように定義しますか?FFバージョンとは?
Gajus 2014

35

JP、あなたの解決策をチェックした後、私はまだページをロードすることに移動する前に画像をプリロードしないというFirefoxの問題を抱えていました。これを発見するにsleep(5)は、サーバーサイドスクリプトにいくつか挿入します。私はこれを解決するように思われるあなたに基づいて以下のソリューションを実装しました。

基本的には、jQueryプリロードプラグインにコールバックを追加しました。これにより、すべての画像が適切にロードされた後に呼び出されます。

// Helper function, used below.
// Usage: ['img1.jpg','img2.jpg'].remove('img1.jpg');
Array.prototype.remove = function(element) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == element) { this.splice(i,1); }
  }
};

// Usage: $(['img1.jpg','img2.jpg']).preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.preloadImages = function(callback) {
  checklist = this.toArray();
  this.each(function() {
    $('<img>').attr({ src: this }).load(function() {
      checklist.remove($(this).attr('src'));
      if (checklist.length == 0) { callback(); }
    });
  });
};

興味深いことに、私のコンテキストでは、これを次のように使用しています。

$.post('/submit_stuff', { id: 123 }, function(response) {
  $([response.imgsrc1, response.imgsrc2]).preloadImages(function(){
    // Update page with response data
  });
});

うまくいけば、これは(私がしたように)Googleからこのページにアクセスする人が、Ajax呼び出しで画像をプリロードするためのソリューションを探すのに役立ちます。


2
Array.prototypeを台無しにすることに関心がない場合は、代わりに次のようにできますchecklist = this.lengthchecklist--if (checklist == 0) callback();
。onload

3
すべては問題ありませんが、所有していないオブジェクトに新しいメソッドを追加したり、既存のメソッドを削除したりすることは、JavaScriptの最悪の慣行の1つです。
Rihards 2012

素晴らしく迅速ですが、このコードは、画像の1つが壊れているか、ロードできない場合、コールバックを起動しません。
SammyK 2012年

.attr({ src: this }).load(function() {...})しなければならない.load(function() {...}).attr({ src: this })そうでなければ、キャッシュの問題を持っています。
Kevin B

25

次の1行のjQueryコードは、DOM要素imgを表示せずに作成(およびロード)します。

$('<img src="img/1.jpg"/>');

4
@huzzah-スプライトを使用するだけの方がいいかもしれません。httpリクエストの減少。:)
Alex K

22
$.fn.preload = function (callback) {
  var length = this.length;
  var iterator = 0;

  return this.each(function () {
    var self = this;
    var tmp = new Image();

    if (callback) tmp.onload = function () {
      callback.call(self, 100 * ++iterator / length, iterator === length);
    };

    tmp.src = this.src;
  });
};

使い方は非常に簡単です:

$('img').preload(function(perc, done) {
  console.log(this, perc, done);
});

http://jsfiddle.net/yckart/ACbTK/


これは本当に良い答えです。本当に最高の投票された答えであるはずです。
Sleepycal 2014年

1
いくつかの説明の言葉は良かったでしょう。
robsch 2017年

良い答えですが、lorempixel.comの代わりにpicsum.photos を使用することを勧めします
Aleksandar

19

これを処理する小さなプラグインがあります。

これは、waitForImagesと呼ばimgれ、CSS内の画像への参照を持つ要素または任意の要素を処理できdiv { background: url(img.png) }ます。

CSSで参照されているものを含むすべての画像を単にロードたい場合は、次のようにします:)

$('body').waitForImages({
    waitForAll: true,
    finished: function() {
       // All images have loaded.
    }  
});

このプラグインにより、ページにまだ表示されていない画像が読み込まれるのですか、それとも既に読み込まれる予定の画像にのみイベントをアタッチするのですか?
Dave Cameron

@DaveCameron画像が表示されているかどうかは考慮されません。あなたは簡単にそれをフォークして変更することができます- :visibleカスタムセレクターに追加するだけです。
アレックス2012年

このプラグインは非常に興味深く見えます。ただし、jqueryのドキュメントでは、loadイベントを画像に適用すると、「一貫して機能せず、確実にクロスブラウザしない」ことが強調されています。プラグインはどうやってそれを回避することができましたか?
EleventyOne 2013年

@EleventyOneカスタムセレクターに関してソースを確認します。
アレックス、2013年

@alexこのプラグインは、要素の:hoverのcssに設定されている画像をどのように読み込みますか?それは私には効かない
フィリップ・ホフマン'27年

13

あなたはcss display:none;ルールを使用してhtmlのどこかに画像をロードし、jsまたはjqueryで必要なときにそれらを表示することができます

プリロードにjsまたはjquery関数を使用しないでくださいcssルール対実行されるjsの多くの行

例:HTML

<img src="someimg.png" class="hide" alt=""/>

CSS:

.hide{
display:none;
}

jQuery:

//if want to show img 
$('.hide').show();
//if want to hide
$('.hide').hide();

jquery / javascriptによる画像のプリロードは適切ではありません。画像がページに読み込まれるまでに数ミリ秒かかります。スクリプトが解析および実行されるまでに数ミリ秒かかるため、特に大きな画像の場合、hmlで非表示にするとパフォーマンスも向上します。原因の画像は、あなたがそれを示すまで、まったく表示されることなく実際にプリロードされます!


2
このアプローチに関する詳細情報はここで見つけることができます:perishablepress.com/...
gdelfino

3
ただし、この手法には大きな欠点があることに注意する必要があります。すべての画像が読み込まれるまで、ページは完全に読み込まれません。プリロードするイメージの数とそのサイズによっては、これに時間がかかる場合があります。さらに悪いことに、<img>タグで高さと幅が指定されていない場合、一部のブラウザーは、ページの残りの部分をレンダリングする前に、イメージがフェッチされるまで待機することがあります。

@Alexあなたはとにかくimgをロードする必要があります。htmlでそれらをロードし、あらゆる種類の点滅や半分ロードされたイメージを回避するかどうか、または安定しない解決策のためにもっと高速にしたい場合
その

また、JavaScriptを使用してHTMLタグを作成することは、私の2セントではまったく読めないと思います
itme

1
私は非常に複雑なプロジェクトのための非常に迅速な解決策を必要としていました。
Germstorm 2013年

13

このjquery imageLoaderプラグインはちょうど1.39kbです

使用法:

$({}).imageLoader({
    images: [src1,src2,src3...],
    allcomplete:function(e,ui){
        //images are ready here
        //your code - site.fadeIn() or something like that
    }
});

画像を同期または非同期のどちらでロードするか、および個々の画像ごとに完全なイベントをロードするかどうかなど、他のオプションもあります。


@AamirAfridiなぜですか?
Ian

1
@Ianは、コールバックが発生するまでにドキュメントがすでに準備されているためです。$(document).readyは、DOMがロードされていることを確認するために使用されます。コールバックに関しては、すべての画像が読み込まれることを意味します。つまり、yoru DOMが読み込まれるため、コールバック内にdocument.readyは必要ありません。
アーミルアフリディ2013年

1
@AamirAfridiドキュメントがコールバックで準備ができている保証はありません...どこからそれを推測していますか?プラグインのページにはallcomplete、DOMの準備ができた後にコールバックが実行されることを示すものは何もありません。DOMの準備ができた後で画像の読み込みが完了する可能性はかなり高いですが、想定する理由はありません。コールバックが魔法で、DOMの準備ができた後に実行されると思う理由はわかりません...どこから取得したのか説明できますか?画像が読み込まれたからといって、DOMの準備ができているわけではありません
Ian

@AamirAfridiそしてプラグインのドキュメントには次のようにも書かれています:NB to use this as an image preloader simply put your $(document).ready(function(){}); into your 'allcomplete' event : > simples!...この答えが示すことを直接推奨しています。
Ian

5
@AamirAfridiそれはこの状況には意味がありません。プラグインはプリローダーです。できるだけ早く実行したい。そして、あなたはできるだけ早く火災にしたい、とすることをDOMに依存しないものがたくさんありますその後、 DOMの準備ができたときに、何かをするには。
Ian

9

プラグインを使わずにjQueryに画像をプリロードしてコールバック関数を取得する簡単な方法はimg、一度に複数のタグを作成し、応答をカウントすることです。

function preload(files, cb) {
    var len = files.length;
    $(files.map(function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

preload(["one.jpg", "two.png", "three.png"], function() {
    /* Code here is called once all files are loaded. */
});
    

IE7をサポートしたい場合は、これより少しきれいではないバージョンを使用する必要があることに注意してください(他のブラウザーでも機能します)。

function preload(files, cb) {
    var len = files.length;
    $($.map(files, function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

7

これをありがとう!私はJPの答えに少しリフを追加すると思います-これが誰かに役立つかどうかはわかりませんが、この方法では画像の配列を作成する必要がなく、大きな画像をすべてプリロードできます親指に正しく名前を付けます。これは、すべてのページをhtmlで記述している人がいるため便利です。これにより、ページの手順が1つ少なくなり、画像配列を作成する必要がなくなり、問題が発生する可能性があります。

$("img").each(function(){
    var imgsrc = $(this).attr('src');
    if(imgsrc.match('_th.jpg') || imgsrc.match('_home.jpg')){
      imgsrc = thumbToLarge(imgsrc);
      (new Image()).src = imgsrc;   
    }
});

基本的には、ページ上の各画像について、各画像のsrcを取得し、特定の基準(サムまたはホームページの画像)に一致する場合、名前を変更し(画像srcの基本的な文字列置換)、画像をロードします。 。

私の場合、ページはすべてimage_th.jpgのような名前のサム画像でいっぱいで、対応するすべての大きな画像はimage_lg.jpgという名前でした。親指を大きくすると、_th.jpgが_lg.jpgに置き換えられ、すべての大きな画像がプリロードされます。

これが誰かを助けることを願っています。


3
    jQuery.preloadImage=function(src,onSuccess,onError)
    {
        var img = new Image()
        img.src=src;
        var error=false;
        img.onerror=function(){
            error=true;
            if(onError)onError.call(img);
        }
        if(error==false)    
        setTimeout(function(){
            if(img.height>0&&img.width>0){ 
                if(onSuccess)onSuccess.call(img);
                return img;
            }   else {
                setTimeout(arguments.callee,5);
            }   
        },0);
        return img; 
    }

    jQuery.preloadImages=function(arrayOfImages){
        jQuery.each(arrayOfImages,function(){
            jQuery.preloadImage(this);
        })
    }
 // example   
    jQuery.preloadImage(
        'img/someimage.jpg',
        function(){
            /*complete
            this.width!=0 == true
            */
        },
        function(){
            /*error*/
        }
    )

7
Stack Overflowへようこそ!コードのブロックを投稿するだけでなく、このコードが提起された問題を解決する理由を説明してください。説明がなければ、これは答えではありません。
Martijn Pieters

3

次のコードを使用します。

$("#myImage").attr("src","img/spinner.gif");

var img = new Image();
$(img).load(function() {
    $("#myImage").attr("src",img.src);
});
img.src = "http://example.com/imageToPreload.jpg";

最初にloadイベントにバインドしてから、srcを設定します。
Kevin B

1

マニフェストファイルを使用して、(最新の)Webブラウザーに、関連するすべての画像を読み込んでキャッシュするように指示します。Gruntとgrunt-manifestを使用してこれを自動的に実行し、プリロードスクリプト、キャッシュ無効化プログラム、CDNなどを心配する必要はありません。

https://github.com/gunta/grunt-manifest


0

これはIE9でも機能します。

$('<img src="' + imgURL + '"/>').on('load', function(){ doOnLoadStuff(); });

1
これは最終的にキャッシングが原因で失敗します。src属性を設定する前に、必ずロードイベントをバインドしてください。
Kevin B

0

Google Maps APIのカスタムオーバーレイでこれを実現したいと考えていました。彼らのサンプルコードは単にJSを使用してIMG要素を挿入し、画像が読み込まれるまで画像プレースホルダーボックスが表示されます。私はここで私のために働いた答えを見つけました:https : //stackoverflow.com/a/10863680/2095698

$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});

これは前に提案されたように画像をプリロードし、img URLがロードされた後、ハンドラーを使用してimgオブジェクトを追加します。jQueryのドキュメントでは、キャッシュされた画像はこのイベント/ハンドラコードでは適切に機能しないと警告していますが、FireFoxとChromeでは問題なく機能し、IEについて心配する必要はありません。


ご存知のように、これはキャッシュされた画像ではうまく機能しません。回避策は、最初にロードイベントをバインドし、次にsrc属性を設定することです。
Kevin B

-1
function preload(imgs) {
    $(imgs).each(function(index, value) {
        $('<img />').attr('src', value).appendTo('body').css('display', 'none');
    });
}

.attr('src',value) ない .attr('src',this)

指摘するだけです:)


this渡されるコールバック内のスコープ$.eachは、反復される値に割り当てられます。
Oybek 2013

?$(['img1.jpg'、 'img2.jpg'、 'img3.jpg'])。each(function(index、value){console.log(value); // img1.jpg console.log(this) ; // String {0 = "i"、1 = "m"、2 = "g"、more ...} $( '<img />')。attr( 'src'、this).appendTo( ' body ')。css(' display '、' none ');});
ウィシャー2013

うーん。あなたはここにいると思います。たとえば、$("div").each(function(i, el){ console.log(el == this);});すべてtrueのを生成します。配列の反復は異なる動作をするようです。
オイベク2013

-2

coffeescriptの5行

array = ['/img/movie1.png','/img/movie2.png','/img/movie3.png']

$(document).ready ->
  for index, image of array
    img[index] = new Image()
    img[index].src = image

2
OPの問題を解決するためにソリューションがどのように機能するかを拡張できますか?そして、おそらくあなたのコードをコメントして、他の人がより簡単に理解できるようにしますか?
Ro Yo Mi

-4

actionscriptを少し知っている人は、最小限の労力でフラッシュプレーヤーをチェックし、フラッシュプリローダーを作成して、html5 / Javascript / Jqueryにエクスポートすることもできます。フラッシュプレーヤーが検出されない場合に使用するには、html5プレーヤーに戻るyoutubeの役割でこれを行う方法の例を確認します。そして、独自のプレーヤーを作成します。詳細はわかりません。まだ開始していないため、忘れていない場合は後で投稿し、標準のJqueryコードを試してみます。


これは解決策ではありません。ブラウザはデフォルトでFlashプレーヤーをサポートしていません。ブラウザのネイティブ言語であるJavaScriptで簡単に実現できます。
ウスマンアフメド

私は2012年からフラッシュが嫌いだったことを覚えています...それは普通ではありませんでした...どこに行ってもフラッシュという言葉を使っただけで攻撃を受けました。
Peter Gruppelaar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.