2010-09-05 10 views
159

¿Puede decirme si la función que escribí a continuación es suficiente para cargar imágenes en la mayoría de los navegadores, si no todos, que se usan comúnmente en la actualidad?Precarga de JavaScript Imágenes

function preloadImage(url) 
{ 
    var img=new Image(); 
    img.src=url; 
} 

Tengo una matriz de imageURLs que hago un bucle y llamo a la función preloadImage para cada URL.

+9

Tenga en cuenta que algunos (todos los navegadores?) Dará a conocer la imagen después de algunos segundos si no lo ha usado. Para evitar esto, mantenga una referencia al objeto 'img', p. en una matriz en el alcance principal. – Tamlyn

+1

¿Qué quiere decir con "liberar la imagen"? Si el navegador lo guardó en la memoria caché, permanecerá allí, ¿no? – Francisc

+2

Permanecerá almacenado en caché en el disco, pero no en la RAM, y algunas veces el disco es demasiado lento (por ejemplo, animando una secuencia). – Tamlyn

Respuesta

82

Sí. Esto debería funcionar en todos los principales navegadores.

18

CSS2 alternativa: http://www.thecssninja.com/css/even-better-image-preloading-with-css2

body:after { 
    content: url(img01.jpg) url(img02.jpg) url(img03.jpg); 
    display: none; 
} 

CSS3 alternativa: https://perishablepress.com/preload-images-css3/ (H/T Linh presa)

.preload-images { 
    display: none; 
    width: 0; 
    height: 0; 
    background: url(img01.jpg), 
       url(img02.jpg), 
       url(img03.jpg); 
} 

NOTA: Imágenes en un recipiente con display:none podría no precarga. Quizás visibilidad: oculto funcionará mejor, pero no he probado esto. Gracias Marco Del Valle por señalar esto

+0

Gracias mplungjan. Aunque no me ayuda con este caso particular, es bueno saberlo. – Francisc

+4

¿Tengo razón al decir que esto ralentizará la carga de la página porque estas imágenes deben descargarse antes de que la página pueda iniciar el evento de carga? – Jakub

+0

Posiblemente. ¿Por qué no intentarlo? – mplungjan

9

Este enfoque es un poco más elaborado. Aquí almacena todas las imágenes precargadas en un contenedor, puede ser un div. Y después de que puedas mostrar las imágenes o moverlas dentro del DOM a la posición correcta.

function preloadImg(containerId, imgUrl, imageId) { 
    var i = document.createElement('img'); // or new Image() 
    i.id = imageId; 
    i.onload = function() { 
     var container = document.getElementById(containerId); 
     container.appendChild(this); 
    }; 
    i.src = imgUrl; 
} 

Try it here, también he añadido algunos comentarios

+1

Votos abajo deben ser comentados – freedev

+0

Nuevamente, por favor realmente me importa mi respuesta. Por favor comenten sus votos abajo para permitirme mejorar mi respuesta – freedev

+0

Creo que los votos a favor se deben a que está accediendo a la dom cuando se llama a la función, lo que podría ser problemático si tiene otra función accediendo a la dom para localizar el elemento al mismo tiempo. – Programmer

10

le recomiendo que utilice un try/catch para evitar algunos problemas posibles:

POO:

var preloadImage = function (url) { 
     try { 
      var _img = new Image(); 
      _img.src = url; 
     } catch (e) { } 
    } 

estándar:

function preloadImage (url) { 
     try { 
      var _img = new Image(); 
      _img.src = url; 
     } catch (e) { } 
    } 

Además, aunque me encanta DOM, los viejos y estúpidos navegadores pueden tener problemas con DOM, así que evítenlo en mi humilde opinión, en contra de la contribución de freedev. Image() tiene mejor soporte en los viejos buscadores de basura.

+7

No creo que esta sea la forma de detectar errores al cargar Image en javascript; hay algo así como _img.onerror que puede (¿debería?) Ser utilizado. – Greg0ry

+1

¿Cuáles son los "posibles problemas"? – Kissaki

+0

Problemas como soporte para el comando. Consulte el sitio "puedo usar" para ver si un navegador al que se le requiere soporte admite un comando de javascript. – Dave

30

Pruebe esto, creo que esto es mejor.

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

//-- usage --// 
preload(
    "http://domain.tld/gallery/image-001.jpg", 
    "http://domain.tld/gallery/image-002.jpg", 
    "http://domain.tld/gallery/image-003.jpg" 
) 

Fuente: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

+1

ordenado y ordenado! – JackDev

+3

no hay controlador 'onload' para ninguna de las imágenes – Benny

+1

¿Podría explicar por qué esto es mejor? – JJJ

3

Si esto va a funcionar, sin embargo navegadores le límite (4-8) entre las llamadas reales y por lo tanto no cache/precargar todas las imágenes deseadas.

Una mejor manera de hacer esto es llamar proceso de carga antes de usar la imagen de este modo:

function (imageUrls, index) { 
    var img = new Image(); 

    img.onload = function() { 
     console.log('isCached: ' + isCached(imageUrls[index])); 
     *DoSomething..* 

    img.src = imageUrls[index] 
} 

function isCached(imgUrl) { 
    var img = new Image(); 
    img.src = imgUrl; 
    return img.complete || (img .width + img .height) > 0; 
} 
+0

¿Puedes vincular alguna referencia sobre el límite de este navegador? – nulll

+0

Es difícil encontrar una referencia (al menos nunca encontré una), pero Usé mi propio proyecto para probar esto mientras miraba de cerca lo que se cargó desde caché y llamadas al servidor usando la pestaña de red de Chrome en las herramientas de desarrollador de Chrome (f12). Encontré el mismo comportamiento en Firefox y en el uso de dispositivos móviles. – Robin

7

En mi caso fue útil añadir una devolución de llamada a la función de proceso de carga:

function preloadImage(url, callback) 
{ 
    var img=new Image(); 
    img.src=url; 
    img.onload = callback; 
} 

Y luego envolverlo para el caso de un conjunto de direcciones URL a las imágenes que se precargado con devolución de llamada en la que todo está hecho: https://jsfiddle.net/4r0Luoy7/

function preloadImages(urls, allImagesLoadedCallback){ 
    var loadedCounter = 0; 
    var toBeLoadedNumber = urls.length; 
    urls.forEach(function(url){ 
    preloadImage(url, function(){ 
     loadedCounter++; 
      console.log('Number of loaded images: ' + loadedCounter); 
     if(loadedCounter == toBeLoadedNumber){ 
     allImagesLoadedCallback(); 
     } 
    }); 
    }); 
    function preloadImage(url, anImageLoadedCallback){ 
     var img = new Image(); 
     img.src = url; 
     img.onload = anImageLoadedCallback; 
    } 
} 

// Let's call it: 
preloadImages([ 
    '//upload.wikimedia.org/wikipedia/commons/d/da/Internet2.jpg', 
    '//www.csee.umbc.edu/wp-content/uploads/2011/08/www.jpg' 
], function(){ 
    console.log('All images were loaded'); 
}); 
1

Aquí es mi enfoque:

var preloadImages = function (srcs, imgs, callback) { 
    var img; 
    var remaining = srcs.length; 
    for (var i = 0; i < srcs.length; i++) { 
     img = new Image; 
     img.onload = function() { 
      --remaining; 
      if (remaining <= 0) { 
       callback(); 
      } 
     }; 
     img.src = srcs[i]; 
     imgs.push(img); 
    } 
}; 
Cuestiones relacionadas