removeattr - ¿La mejor forma definitiva de cargar imágenes usando JavaScript/jQuery?
removeattr disabled (8)
A partir de enero de 2013 ninguno de los métodos descritos aquí funcionó para mí, así que esto es lo que hizo, probó y trabajó con Chrome 25 y Firefox 18. Utiliza jQuery y este complemento para solucionar las peculiaridades del evento de carga:
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();
}
}
Uso:
preload([''/img/a.png'', ''/img/b.png'', ''/img/c.png''], function() {
console.log("done");
});
Tenga en cuenta que obtendrá resultados mixtos si la memoria caché está deshabilitada, lo que es por defecto en Chrome cuando las herramientas de desarrollador están abiertas, así que tenlo en cuenta.
Soy plenamente consciente de que esta pregunta ha sido formulada y respondida en todas partes, tanto en SO como en off. Sin embargo, cada vez parece haber una respuesta diferente, por ejemplo, this , this y that .
No me importa si está usando jQuery o no, lo importante es que funciona, y es un navegador cruzado.]
Entonces, ¿cuál es la mejor manera de precargar imágenes?
Aquí va mi solución simple con un desvanecimiento en la imagen después de que se carga.
function preloadImage(_imgUrl, _container){
var image = new Image();
image.src = _imgUrl;
image.onload = function(){
$(_container).fadeTo(500, 1);
};
}
Desafortunadamente, eso depende de tu propósito. Si planea usar las imágenes por motivos de estilo, su mejor opción es usar sprites. http://www.alistapart.com/articles/sprites2
Sin embargo, si planea usar las imágenes en las etiquetas <img>, querrá precargarlas con
function preload(sources)
{
var images = [];
for (i = 0, length = sources.length; i < length; ++i) {
images[i] = new Image();
images[i].src = sources[i];
}
}
(fuente modificada tomada de ¿Cuál es la mejor manera de precargar múltiples imágenes en JavaScript? )
El uso de una new Image()
no implica el gasto de usar métodos DOM, pero se agregará a la cola una nueva solicitud para la imagen especificada. Como la imagen es, en este punto, no realmente agregada a la página, no hay ninguna repetición implicada. Sin embargo, recomendaría agregar esto al final de la página (como deberían ser todos los scripts, cuando sea posible) para evitar que contenga más elementos críticos.
Editar: editado para reflejar los comentarios que señalan correctamente que se requieren objetos de Image
separados para funcionar correctamente. Gracias, y es malo por no verificarlo más de cerca.
Edit2: editado para hacer la reutilización más obvia
Editar 3 (3 años después):
Debido a los cambios en la forma en que los navegadores manejan las imágenes no visibles (pantalla: ninguna o, como en esta respuesta, nunca adjuntas al documento), se prefiere un nuevo enfoque para la precarga.
Puede usar una solicitud de Ajax para forzar la recuperación temprana de imágenes. Usando jQuery, por ejemplo:
jQuery.get(source);
O en el contexto de nuestro ejemplo anterior, podrías hacer:
function preload(sources)
{
jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
Tenga en cuenta que esto no se aplica al caso de los sprites que están bien tal como están. Esto es solo para cosas como galerías de fotos o diapositivas / carruseles con imágenes donde las imágenes no se cargan porque no son visibles inicialmente.
También tenga en cuenta que este método no funciona para IE (ajax normalmente no se utiliza para recuperar datos de imágenes).
En mi opinión, el uso de Multipart XMLHttpRequest introducido por algunas bibliotecas será una solución preferida en los próximos años. Sin embargo, IE <v8, aún no admite datos: uri (incluso IE8 tiene soporte limitado, permitiendo hasta 32kb). Aquí hay una implementación de precarga de imágenes en paralelo: http://code.google.com/p/core-framework/wiki/ImagePreloading , está incluido en el marco, pero aún vale la pena echarle un vistazo.
Esto fue hace mucho tiempo, así que no sé cuántas personas todavía están interesadas en precargar una imagen.
Mi solución fue aún más simple.
Acabo de usar CSS.
#hidden_preload {
height: 1px;
left: -20000px;
position: absolute;
top: -20000px;
width: 1px;
}
Mira esto:
http://www.mattfarina.com/2007/02/01/preloading_images_with_jquery
Pregunta relacionada sobre SO:
Para mi caso de uso, tenía un carrusel con imágenes de pantalla completa que quería cargar previamente. Sin embargo, dado que las imágenes se muestran en orden, y cada una de ellas puede tardar unos segundos en cargarse, es importante que las cargue en orden, secuencialmente.
Para esto utilicé el método waterfall()
la biblioteca asíncrona ( 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);
Esto funciona al crear una matriz de funciones, cada función pasa el parámetro callback()
que necesita ejecutar para llamar a la siguiente función en la matriz. El primer parámetro de callback()
de callback()
es un mensaje de error, que saldrá de la secuencia si se proporciona un valor no nulo, por lo que pasamos nulo cada vez.
Spriting
Como otros han mencionado, Sprit funciona bastante bien por una variedad de razones, sin embargo, no es tan bueno como se supone.
- Por el lado positivo, terminas haciendo solo una solicitud HTTP para tus imágenes. YMMV sin embargo.
- En el lado negativo, estás cargando todo en una solicitud HTTP. Como la mayoría de los navegadores actuales están limitados a 2 conexiones simultáneas, la solicitud de imágenes puede bloquear otras solicitudes. Por lo tanto, YMMV y algo así como el fondo de tu menú pueden no reproducirse por un momento.
- Varias imágenes comparten la misma paleta de colores, por lo que hay un poco de ahorro, pero este no es siempre el caso, y aún así es insignificante.
- La compresión se mejora porque hay más datos compartidos entre las imágenes.
Tratar con formas irregulares es complicado sin embargo. Combinar todas las imágenes nuevas en la nueva es otra molestia.
Enfoque Low Jack usando etiquetas <img>
Si estás buscando la solución más definitiva , entonces debes elegir el enfoque low-jack que aún prefiero. Cree vínculos <img> a las imágenes al final de su documento y configure el width
y height
en 1x1 píxel y, además, colóquelos en un div oculto. Si están al final de la página, se cargarán después de otro contenido.