Retrollamada de jQuery en la carga de la imagen (incluso cuando la imagen está en caché)

Quiero hacer:

$("img").bind('load', function() { // do stuff }); 

Pero el evento de carga no se dispara cuando la imagen se carga desde la memoria caché. Los documentos jQuery sugieren un complemento para arreglar esto, pero no funciona

Si el src ya está configurado, el evento se activará en el caso en caché, incluso antes de que el controlador del evento esté enlazado. Para solucionar esto, puede recorrer y verificar el evento basado en .complete , así:

 $("img").one("load", function() { // do stuff }).each(function() { if(this.complete) $(this).load(); }); 

Tenga en cuenta el cambio de .bind() a .one() para que el controlador de eventos no se ejecute dos veces.

¿Puedo sugerirle que lo vuelva a cargar en un objeto de imagen que no sea DOM? Si está almacenado en caché, esto no llevará tiempo, y la carga continuará activa. Si no está almacenado en la memoria caché, activará la carga cuando se cargue la imagen, que debería coincidir con el final de la carga de la versión DOM de la imagen.

Javascript:

 $(document).ready(function() { var tmpImg = new Image() ; tmpImg.src = $('#img').attr('src') ; tmpImg.onload = function() { // Run onload code. } ; }) ; 

Actualizado (para manejar múltiples imágenes y con un archivo adjunto onload correctamente ordenado):

 $(document).ready(function() { var imageLoaded = function() { // Run onload code. } $('#img').each(function() { var tmpImg = new Image() ; tmpImg.onload = imageLoaded ; tmpImg.src = $(this).attr('src') ; }) ; }) ; 

Mi solución simple, no necesita ningún complemento externo y para casos comunes debería ser suficiente:

 /** * Trigger a callback when the selected images are loaded: * @param {String} selector * @param {Function} callback */ var onImgLoad = function(selector, callback){ $(selector).each(function(){ if (this.complete || /*for IE 10-*/ $(this).height() > 0) { callback.apply(this); } else { $(this).on('load', function(){ callback.apply(this); }); } }); }; 

Úselo así:

 onImgLoad('img', function(){ // do stuff }); 

por ejemplo, para fundir las imágenes en la carga, puede hacer:

 $('img').hide(); onImgLoad('img', function(){ $(this).fadeIn(700); }); 

O como alternativa, si prefieres un enfoque tipo jquery:

 /** * Trigger a callback when 'this' image is loaded: * @param {Function} callback */ (function($){ $.fn.imgLoad = function(callback) { return this.each(function() { if (callback) { if (this.complete || /*for IE 10-*/ $(this).height() > 0) { callback.apply(this); } else { $(this).on('load', function(){ callback.apply(this); }); } } }); }; })(jQuery); 

y úsalo de esta manera:

 $('img').imgLoad(function(){ // do stuff }); 

por ejemplo:

 $('img').hide().imgLoad(function(){ $(this).fadeIn(700); }); 

¿De verdad tienes que hacerlo con jQuery? Puede adjuntar el evento onload directamente a su imagen también;

  

Se disparará cada vez que se cargue la imagen, desde la memoria caché o no.

Simplemente tuve este problema yo mismo, busqué en todas partes una solución que no implicara matar mi caché o descargar un complemento.

No vi este hilo inmediatamente, así que encontré otra cosa que es una solución interesante y (creo) digna de publicar aquí:

 $('.image').load(function(){ // stuff }).attr('src', 'new_src'); 

De hecho, obtuve esta idea de los comentarios aquí: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

No tengo idea de por qué funciona, pero lo he probado en IE7 y donde se rompió antes de que funcione.

Espero eso ayude,

Editar

La respuesta aceptada realmente explica por qué:

Si el src ya está configurado, el evento se activará en el caché insertado antes de que se vincule el controlador de eventos.

También puede usar este código con soporte para error de carga:

 $("img").on('load', function() { // do stuff on success }) .on('error', function() { // do stuff on smth wrong (error 404, etc.) }) .each(function() { if(this.complete) { $(this).load(); } else if(this.error) { $(this).error(); } }); 

Una modificación al ejemplo de GUS:

 $(document).ready(function() { var tmpImg = new Image() ; tmpImg.onload = function() { // Run onload code. } ; tmpImg.src = $('#img').attr('src'); }) 

Configure la fuente antes y después de la carga.

Al usar jQuery para generar una nueva imagen con src de la imagen y asignar el método de carga directamente a eso, el método de carga se llama con éxito cuando jQuery termina de generar la nueva imagen. Esto me funciona en IE 8, 9 y 10

 $('', { "src": $("#img").attr("src") }).load(function(){ // Do something }); 

Simplemente vuelva a agregar el argumento src en una línea separada después de que se defina imgject. Esto engañará a IE para que active el evento chaval. Es feo, pero es la solución más simple que he encontrado hasta ahora.

 jQuery('', { src: url, id: 'whatever' }) .load(function() { }) .appendTo('#someelement'); $('#whatever').attr('src', url); // trigger .load on IE 

Te puedo dar un pequeño consejo si quieres hacer esto:

 

Si haces eso cuando el navegador almacena imágenes en la memoria caché, no es un problema, siempre se muestra img pero se carga img debajo de una imagen real.

Tuve este problema con IE donde el e.target.width no estaría definido. El evento de carga se dispararía pero no pude obtener las dimensiones de la imagen en IE (Chrome + FF funcionó).

Resulta que debe buscar e.currentTarget.naturalWidth y e.currentTarget.naturalHeight .

Una vez más, IE hace las cosas de manera propia (más complicada).

Una solución que encontré https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (Este código fue tomado directamente del comentario)

 var photo = document.getElementById('image_id'); var img = new Image(); img.addEventListener('load', myFunction, false); img.src = 'http://newimgsource.jpg'; photo.src = img.src; 

Puede resolver su problema utilizando el complemento JAIL que también le permite cargar imágenes en modo perezoso (mejorando el rendimiento de la página) y pasar la callback como parámetro

 $('img').asynchImageLoader({callback : function(){...}}); 

El HTML debería verse como

  

Si quieres una solución de CSS puro, este truco funciona muy bien: utiliza el objeto de transformación. Esto también funciona con imágenes cuando están en caché o no:

CSS:

 .main_container{ position: relative; width: 500px; height: 300px; background-color: #cccccc; } .center_horizontally{ position: absolute; width: 100px; height: 100px; background-color: green; left: 50%; top: 0; transform: translate(-50%,0); } .center_vertically{ position: absolute; top: 50%; left: 0; width: 100px; height: 100px; background-color: blue; transform: translate(0,-50%); } .center{ position: absolute; top: 50%; left: 50%; width: 100px; height: 100px; background-color: red; transform: translate(-50%,-50%); } 

HTML:

 

Ejemplo de Codepen

Codepen LESS ejemplo