Il modo migliore per precaricare le immagini usando JavaScript / jQuery?

Sono pienamente consapevole che questa domanda è stata posta e ha risposto ovunque, sia su SO che fuori. Tuttavia, ogni volta sembra che ci sia una risposta diversa, per esempio questo , questo e quello .

Non mi interessa se usi jQuery o no – l’importante è che funzioni, ed è cross-browser.]

Quindi, qual è il modo migliore per precaricare le immagini?

Sfortunatamente, ciò dipende dal tuo scopo. Se si prevede di utilizzare le immagini per scopi di stile, la soluzione migliore è utilizzare gli sprite. http://www.alistapart.com/articles/sprites2

Tuttavia, se prevedi di utilizzare le immagini nei tag , dovrai prima caricarle con

function preload(sources) { var images = []; for (i = 0, length = sources.length; i < length; ++i) { images[i] = new Image(); images[i].src = sources[i]; } } 

(fonte modificata presa da Qual è il modo migliore per precaricare più immagini in JavaScript? )

l'utilizzo della new Image() non comporta la spesa per l'utilizzo dei metodi DOM ma una nuova richiesta per l'immagine specificata verrà aggiunta alla coda. Poiché l'immagine è, a questo punto, non effettivamente aggiunta alla pagina, non è previsto alcun re-rendering. Ti consiglio, tuttavia, di aggiungere questo alla fine della pagina (come dovrebbero essere tutti gli script, quando ansible) per evitare che registri elementi più critici.

Modifica: modificato per riflettere correttamente il commento sottolineando che gli oggetti Image separati sono necessari per funzionare correttamente. Grazie, e il mio male per non averlo controllato più da vicino.

Edit2: modificato per rendere la riusabilità più ovvia

Modifica 3 (3 anni dopo):

A causa di cambiamenti nel modo in cui i browser gestiscono le immagini non visibili (display: none o, come in questa risposta, non è mai stato aggiunto al documento) è preferibile un nuovo approccio al pre-caricamento.

È ansible utilizzare una richiesta Ajax per forzare il recupero anticipato delle immagini. Usando jQuery, ad esempio:

 jQuery.get(source); 

O nel contesto del nostro precedente esempio, potresti fare:

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

Nota che questo non si applica al caso degli sprites che vanno bene così com'è. Questo è solo per cose come gallerie fotografiche o cursori / caroselli con immagini in cui le immagini non vengono caricate perché inizialmente non sono visibili.

Si noti inoltre che questo metodo non funziona per IE (ajax normalmente non viene utilizzato per recuperare i dati dell'immagine).

sprite

Come altri hanno già accennato, lo sprite funziona abbastanza bene per una serie di motivi, tuttavia, non è buono come è stato dimostrato.

  • Sul lato positivo, si finisce per fare solo una richiesta HTTP per le tue immagini. YMMV però.
  • Sul lato negativo si sta caricando tutto in una richiesta HTTP. Poiché la maggior parte dei browser correnti è limitata a 2 connessioni simultanee, la richiesta di immagine può bloccare altre richieste. Quindi YMMV e qualcosa come lo sfondo del tuo menu potrebbe non essere visualizzato per un po ‘.
  • Più immagini condividono la stessa tavolozza di colors, quindi c’è un po ‘di risparmio, ma questo non è sempre il caso e anche così è trascurabile.
  • La compressione è migliorata perché vi sono più dati condivisi tra le immagini.

Trattare con forms irregolari è però complicato. Unire tutte le nuove immagini a quelle nuove è un altro fastidio.

Approccio low-jack usando i tag

Se stai cercando la soluzione più definitiva , dovresti seguire l’approccio low-jack che preferisco ancora. Crea collegamenti alle immagini alla fine del documento e imposta width e height a 1×1 pixel e aggiungili in un div nascosto. Se sono alla fine della pagina, saranno caricati dopo altri contenuti.

A partire da gennaio 2013 nessuno dei metodi descritti qui ha funzionato per me, quindi ecco cosa ha invece, testato e funzionante con Chrome 25 e Firefox 18. Utilizza jQuery e questo plug-in per aggirare le anomalie dell’evento di caricamento:

 function preload(sources, callback) { if(sources.length) { var preloaderDiv = $('
').prependTo(document.body); $.each(sources, function(i,source) { $("").attr("src", source).appendTo(preloaderDiv); if(i == (sources.length-1)) { $(preloaderDiv).imagesLoaded(function() { $(this).remove(); if(callback) callback(); }); } }); } else { if(callback) callback(); } }

Uso:

 preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() { console.log("done"); }); 

Tieni presente che otterrete risultati misti se la cache è disabilitata, che è di default su Chrome quando gli strumenti di sviluppo sono aperti, quindi tienilo a mente.

A mio parere, l’utilizzo di Multipart XMLHttpRequest introdotto da alcune librerie sarà una soluzione preferita negli anni successivi. Tuttavia IE http://code.google.com/p/core-framework/wiki/ImagePreloading , è impacchettato in un framework ma vale comunque la pena dare un’occhiata.

Questo è stato da molto tempo fa quindi non so quante persone sono ancora interessati a precaricare un’immagine.

La mia soluzione era ancora più semplice.

Ho appena usato i CSS.

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

Ecco la mia soluzione semplice con una dissolvenza nell’immagine dopo che è stata caricata.

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

Per il mio caso d’uso ho avuto un carosello con immagini a schermo intero che volevo precaricare. Tuttavia, poiché le immagini vengono visualizzate in ordine, e potrebbero essere necessari alcuni secondi per caricarle, è importante caricarle in ordine, in sequenza.

Per questo ho usato il metodo waterfall() della libreria async ( 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.load(function() { callback(null); })[0].src = url; }); }); async.waterfall(image_preload_array); 

Questo funziona creando una serie di funzioni, ogni funzione riceve il parametro callback() che deve essere eseguito per chiamare la funzione successiva nell’array. Il primo parametro di callback() è un messaggio di errore, che uscirà dalla sequenza se viene fornito un valore non nullo, quindi passiamo null ogni volta.

Guarda questo:

http://www.mattfarina.com/2007/02/01/preloading_images_with_jquery

Domanda relativa su SO:

jquery precarico nascosto