JQuery ile görüntüleri önceden yükleme


689

JavaScript ile görüntüleri önceden yüklemenin hızlı ve kolay bir yolunu arıyorum. Bu önemli ise jQuery kullanıyorum.

Bunu burada gördüm ( 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" });
  }
};

Ama, istediğim şey için biraz fazla görünüyor!

Bunu yapmak orada jQuery eklentileri olduğunu biliyorum ama hepsi biraz (büyüklük) büyük görünüyor; Görüntüleri önceden yüklemenin hızlı, kolay ve kısa bir yoluna ihtiyacım var!


10
$.each(arguments,function(){(new Image).src=this});
David Hellsing

Yanıtlar:


969

Hızlı ve kolay:

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'
]);

Veya, bir jQuery eklentisi istiyorsanız:

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

// Usage:

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

25
Tarayıcının önbelleğe almasını sağlamak için resim öğesinin DOM'a eklenmesi gerekmez mi?
JoshNaro

8
$('<img />')Bellekte sadece bir görüntü öğesi oluşturduğuna inanıyorum ( bağlantıya bakınız ). Görünüşe göre '$('<img src="' + this + '" />')aslında gizli bir DIV içinde eleman yaratılacak, çünkü daha "karmaşık". Ancak, bunun çoğu tarayıcı için gerekli olduğunu düşünmüyorum.
JoshNaro

104
Bu bir jQuery eklentisi yazmanın garip bir yoludur. Neden olmasın $.preload(['img1.jpg', 'img2.jpg'])?
alex

12
Bunu içeride aradığınızdan emin olun $(window).load(function(){/*preload here*/});çünkü belgedeki tüm görüntüler ilk önce yüklenir, muhtemelen ilk önce bunlara ihtiyaç duyulur.
Jasper Kennis

12
@RegionalC - Yük olayı ayarlanmadan önce görüntünün yüklenmesi tamamlanırsa , loadolayı ayarlamak için olayı ayarlamak biraz daha güvenli olabilir srcmi? $('<img/>').load(function() { /* it's loaded! */ }).attr('src', this);
sparebytes

102

İşte görüntüleri gerçekte DOM'a yükleyen ve varsayılan olarak gizleyen ilk yanıtın ince bir sürümü.

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

38
hide()daha kısadır css('display', 'none').
alex

6
Bunları DOM'a eklemenin avantajı nedir?
alex

Bunları DOM'a eklemenin avantajını da bilmek istiyorum.
jedmao

11
Deneyimlerime göre, bir görüntüyü DOM'a önceden yüklemek, tarayıcının varlığından ve düzgün bir şekilde önbelleğe alınmasından haberdar olmasını sağlar. Aksi takdirde, görüntü yalnızca tek sayfa uygulamaları için çalışan bellekte bulunur.
Dennis Rongo

Dennis Rongo. Chrome'a ​​DOM sabit rastgele yeniden yüklemeye resim eklenmesi. Teşekkürler!
tmorell

52

JavaScript Image nesnesini kullanın .

Bu işlev, tüm resimleri yükledikten sonra geri aramayı tetiklemenizi sağlar. Ancak, en az bir kaynak yüklenmezse hiçbir zaman geri arama tetiklemeyeceğini unutmayın. Bu, onerrorgeri arama ve loadeddeğeri arttırarak veya hatayı kaldırarak kolayca düzeltilebilir .

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
Doğru olanı yapın, JavaScript Image nesnesini kullanın. insanların bu cevaplarda yanlış bir şey yaptığını gözlemledin mi?
alex

Mükemmel kod. onloadGörüntü önbelleğe alınmış olsa bile bunun olayı tetikleyeceğini düşünmekte haklı mıyım? (Çünkü img.onloadilk ilan edilmiştir). Testlerim bunu gösterdi.
Startec

3
@alex potansiyel olarak, evet. Hedef (bir performans sırası önerir) önyükleme ise o zaman jQuery bağımlı seçenekleri yerine ham JS seçeneği görmeyi tercih ederim.
Charlie Schliesser

Bu çözümü sevdim ancak Firefox'umda işe yaramadığını keşfettim. Sadece ben mi yoksa başkaları da aynı sorunu yaşıyor mu?
Gazillion

@Gazillion daha fazla ayrıntı veriyor. "Çalışmama" yı nasıl tanımlarsınız? FF sürümü nedir?
Gajus

35

JP, Çözümünüzü kontrol ettikten sonra, Firefox'ta sayfayı yüklemeye devam etmeden önce görüntüleri önceden yüklemeyeceği sorunlar yaşıyordum. Bunu bazı sleep(5)sunucu tarafı komut dosyama koyarak keşfettim . Bunu çözmüş gibi görünen aşağıdaki çözümü sizinkine uyguladım.

Temelde jQuery önyükleme eklentisine bir geri arama ekledim, böylece tüm görüntüler düzgün bir şekilde yüklendikten sonra çağrılır.

// 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(); }
    });
  });
};

İlgi alanı dışında, benim bağlamımda, bunu aşağıdaki gibi kullanıyorum:

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

Umarım bu, Google'dan bu sayfaya gelen birisinin (benim yaptığım gibi) Ajax çağrılarına görüntüleri önceden yüklemek için bir çözüm aramasına yardımcı olur.


2
Array.prototype'yi checklist = this.lengthchecklist--if (checklist == 0) callback();
bozmakla ilgilenmeyenler

3
Her şey iyi olurdu, ancak sahip olmadığınız bir nesneye yeni yöntemler eklemek veya mevcut yöntemleri kaldırmak JavaScript'teki en kötü uygulamalardan biridir.
Rihards

Güzel ve hızlı, ancak resimlerden biri bozulursa veya yüklenemezse bu kod asla geri çağrıyı tetiklemez.
SammyK

.attr({ src: this }).load(function() {...})gerektiğini .load(function() {...}).attr({ src: this })aksi takdirde önbellek sorun yaşayabilirsiniz.
Kevin B

25

Bu bir satır jQuery kodu göstermeden bir DOM öğesi img oluşturur (ve yükler):

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

4
@huzzah - Sadece sprite kullanarak daha iyi olabilirsiniz. Daha az http isteği. :)
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;
  });
};

Kullanımı oldukça basit:

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

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


Bu gerçekten iyi bir cevap, gerçekten en çok oy alan cevap imho olmalı.
sleepycal

1
Bazı açıklayıcı kelimeler iyi olurdu.
robsch

İyi cevap, ama lorempixel.com yerine picsum.photos kullanmanızı öneririm
Aleksandar

19

Bunu işleyen küçük bir eklentim var.

Buna waitForImages denir ve imgöğeleri veya CSS'deki bir görüntüye referans olan herhangi bir öğeyi işleyebilir , örn div { background: url(img.png) }.

CSS'de atıfta bulunulanlar da dahil olmak üzere tüm resimleri yüklemek istiyorsanız , işte böyle yapardınız :)

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

Bu eklenti, sayfada henüz görünmeyen görüntülerin yüklenmesine neden oluyor mu yoksa yalnızca önceden yüklenecek görüntülere etkinlik ekliyor mu?
Dave Cameron

@DaveCameron Görüntülerin görünür olup olmadığına saygı göstermez. Kolayca çatallayabilir ve bu değişikliği yapabilirsiniz - sadece :visibleözel seçiciye ekleyin .
alex

Bu eklenti çok ilginç görünüyor. Bununla birlikte, jquery belgeleri , loadolayın görüntülere uygulandığında "tutarlı veya güvenilir bir şekilde çapraz tarayıcıda çalışmadığını" vurgulamaktadır . Eklenti bunun üstesinden gelmeyi nasıl başardı?
EleventyOne

@EleventyOne Özel seçiciyle ilgili kaynağı kontrol edin.
alex

@alex Bu eklenti css on: hover öğesinde ayarlanan görüntüleri nasıl yükler? Benim için çalışmıyor
Philipp Hofmann

13

html'nize css display:none;kuralını kullanarak bir yere resim yükleyebilir , ardından js veya jquery ile istediğiniz zaman gösterebilirsiniz

js veya jquery işlevlerini önceden yüklemek için kullanmayın sadece bir css kuralı Vs yürütülecek birçok js satırı

örnek: 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 ile görüntüleri önceden yüklemek iyi değildir, çünkü görüntüler sayfaya yüklenmek için birkaç milisaniye gerekir + betiğin ayrıştırılması ve yürütülmesi için milisaniye süreniz vardır, özellikle de büyük resimlerdeyse, hml'de gizlemek de performans için daha iyidir, çünkü bunu gösterene kadar görüntü hiç görünmeden gerçekten önceden yüklenir!


2
Bu yaklaşım hakkında daha fazla bilgiyi burada bulabilirsiniz: perishablepress.com/…
gdelfino

3
Ancak, bu tekniğin büyük bir dezavantajı olduğunu bilmeniz gerekir: tüm resimler yüklenene kadar sayfanız tamamen yüklenmeyecektir. Önceden yüklenecek görüntü sayısına ve boyutlarına bağlı olarak bu biraz zaman alabilir. Daha da kötüsü, <img> etiketi bir yükseklik ve genişlik belirtmezse, bazı tarayıcılar sayfanın geri kalanını oluşturmadan önce resim alınana kadar bekleyebilir.

@Alex yine de img yüklemeniz gerekiyor, bunları html ile yüklemeyi ve yanıp sönen ve yarı yüklü görüntüleri herhangi bir türden kaçınmayı seçmekte özgürsünüz veya istikrarlı olmayan bir çözüm için daha fazla hız almak istiyorsanız
itsme

Ayrıca ben gerçekten javascript ile html etiketleri oluşturmak sadece benim 2 sent okunamaz olduğunu düşünüyorum
itsme

1
Çok karmaşık bir proje için çok hızlı bir çözüme ihtiyacım vardı ve hepsi bu.
Mikrop fırtınası

13

Bu jquery imageLoader eklentisi sadece 1.39kb

kullanımı:

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

görüntüleri senkronize veya asenkronize olarak yüklemek isteyip istemediğiniz ve her bir görüntü için eksiksiz bir olay gibi başka seçenekler de vardır.


@AamirAfridi Neden bu?
Ian

1
@Ian çünkü geri arama başlatıldığında belge zaten hazır. $ (document) .ready, DOM'nizin yüklendiğinden emin olmak için kullanılır. Geri arama söz konusu olduğunda, bu, tüm görüntülerin yüklendiği anlamına gelir, bu da yoru DOM'un yüklendiği anlamına gelir, bu nedenle belgeye gerek yoktur.
Aamir Afridi

1
@AamirAfridi Belgenin geri aramada hazır olduğuna dair bir garanti yok ... bunu nereden çıkarıyorsunuz? Eklentinin sayfasında allcomplete, DOM hazır olduktan sonra geri aramanın yürütüldüğünü söyleyen hiçbir şey yok . DOM hazır olduktan sonra görüntülerin yüklenmesini bitirme olasılığı oldukça yüksektir, ancak varsayılması için bir neden yoktur. Geri aramaların neden sihirli olduğunu ve DOM hazır olduktan sonra yürütüldüğünü bilmiyorum ... Bunu nereden aldığınızı açıklayabilir misiniz? Görüntüler yüklendiğinden DOM'un hazır olduğu anlamına gelmez
Ian

@AamirAfridi Ve eklentinin belgeleri bile diyor ki: NB to use this as an image preloader simply put your $(document).ready(function(){}); into your 'allcomplete' event : > simples!... bu cevabın ne gösterdiğini doğrudan tavsiye ediyor.
Ian

5
@AamirAfridi Bu durum için bir anlam ifade etmiyor. Eklenti bir ön yükleyicidir. En kısa zamanda yürütmek istiyorsunuz. Ve en kısa zamanda tetiklemek istediğiniz DOM'ye bağlı olmayan birçok şey var ve daha sonra DOM hazır olduğunda bir şeyler yapın.
Ian

9

JQuery'de görüntüleri önceden yüklemek ve geri arama işlevi almak için hızlı, eklentisiz bir yol, imgaynı anda birden fazla etiket oluşturmak ve yanıtları saymaktır, ör.

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'yi desteklemek istiyorsanız, bu biraz daha az güzel sürümü kullanmanız gerektiğini unutmayın (Bu aynı zamanda diğer tarayıcılarda da çalışır):

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

7

Bunun için teşekkürler! JP'nin cevabına biraz riff eklemek isterdim - bunun kimseye yardım edip etmeyeceğini bilmiyorum, ancak bu şekilde bir dizi görüntü oluşturmak zorunda değilsiniz ve eğer tüm büyük resimlerinizi önceden yükleyebilirsiniz. başparmaklarınızı doğru adlandırın. Bu kullanışlı çünkü tüm sayfaları html ile yazan biri var ve onlar için daha az bir adım sağlar - görüntü dizisi oluşturma ihtiyacını ortadan kaldırır ve şeylerin berbat olabileceği başka bir adım.

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

Temel olarak, sayfadaki her görüntü için her görüntünün src'sini alır, belirli ölçütlerle eşleşiyorsa (bir başparmak veya ana sayfa görüntüsü ise) adı değiştirir (görüntü src'sinde temel bir dize değiştirilir), ardından görüntüleri yükler .

Benim durumumda, sayfa, image_th.jpg gibi bir ad taşıyan küçük resimlerle doluydu ve karşılık gelen tüm büyük görüntüler image_lg.jpg olarak adlandırıldı. Büyük olan başparmak _th.jpg dosyasını _lg.jpg ile değiştirir ve ardından tüm büyük resimleri önceden yükler.

Umarım bu birine yardımcı olur.


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'a hoş geldiniz! Lütfen yalnızca bir kod bloğu göndermek yerine, bu kodun neden ortaya çıkan sorunu çözdüğünü açıklayın . Bir açıklama olmadan, bu bir cevap değildir.
Martijn Pieters

3

Aşağıdaki kodu kullanıyorum:

$("#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";

Önce load olayına bağlanın, sonra src'yi ayarlayın.
Kevin B

1

Web tarayıcılarına ilgili tüm resimleri yükleyip önbelleklemelerini söylemek için bir Manifest dosyası kullanırdım. Bunu otomatik olarak yapmak için Grunt ve grunt-manifest kullanın ve önyükleme komut dosyaları, önbellek geçersizleştiricileri, CDN vb.

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


0

IE9'da bile bu benim için çalışıyor:

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

1
Önbellek nedeniyle bu başarısız olur, src özniteliğini ayarlamadan önce her zaman load olayını bağlayın.
Kevin B

0

Bunu bir Google Haritalar API'sı özel yer paylaşımı ile yapmak istedim. Örnek kodları IMG öğelerini eklemek için sadece JS kullanır ve görüntü yüklenene kadar görüntü yer tutucu kutusu görüntülenir. Burada benim için çalışan bir cevap buldum: https://stackoverflow.com/a/10863680/2095698 .

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

Bu, daha önce önerildiği gibi bir görüntüyü önceden yükler ve img URL'si yüklendikten sonra img nesnesini eklemek için işleyiciyi kullanır. jQuery'nin belgeleri, önbelleğe alınan görüntülerin bu olay / işleyici koduyla iyi çalışmadığı konusunda uyarıyor, ancak FireFox ve Chrome'da benim için çalışıyor ve IE için endişelenmem gerekmiyor.


Bu, bulduğunuz gibi önbelleğe alınmış resimlerle iyi çalışmaz. geçici çözüm, önce load olayını bağlamak, sonra src niteliğini ayarlamaktır.
Kevin B

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

.attr('src',value) değil .attr('src',this)

sadece işaret etmek :)


Aktarılan thisgeri aramanın içindeki kapsam $.each, yinelenmekte olan değere atanır.
Oybek

? $ (['img1.jpg', 'img2.jpg', 'img3.jpg']). her biri (işlev (dizin, değer) {console.log (değer); // img1.jpg console.log (bu) ; // Dize {0 = "i", 1 = "m", 2 = "g", daha fazlası ...} $ ('<img />'). Attr ('src', bu) .appendTo (' gövde '). css (' ekran ',' hiçbiri ');});
Whisher

Hm. Sanırım tam buradasın. Örneğin $("div").each(function(i, el){ console.log(el == this);});, tüm trues; Dizi üzerinden yineleme farklı davranıyor gibi görünüyor.
Oybek

-2

Kahvede 5 satır

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'deki soruyu çözmek için çözümün nasıl çalıştığını genişletebilir misiniz? Ve muhtemelen kodunuzu yorumlayın, böylece diğerleri daha kolay anlayabilir mi?
Ro Yo Mi

-4

Biraz actionscript bilenler için, en az çabayla flash player'ı kontrol edebilir ve html5 / Javascript / Jquery'ye de aktarabileceğiniz bir flash ön yükleyici yapabilirsiniz. Flash oynatıcı algılanmazsa kullanmak için, bunun html5 oynatıcısına geri dönerek youtube rolü ile nasıl yapılacağına dair örnekleri kontrol edin :) Ve kendinizinkini oluşturun. Ben henüz başlamadıysanız, ayrıntılara sahip değilim, eğer unutmazsam, daha sonra yayınlayacağım ve benim için bazı standerd Jquery kodunu deneyeceğim.


Bu bir çözüm değil. Tarayıcı varsayılan olarak Flash oynatıcıyı desteklemez. Yerel tarayıcı dili olan JavaScript ile kolayca elde edilebilir.
Usman Ahmed

2012'den Flash nefret edenleri hatırlıyorum ... normal değildi ... Gittiğim her yerde Flash kelimesini bile kullandığımda saldırıya uğradım.
Peter Gruppelaar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.