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 de jQuery sugieren un complemento para solucionar esto, pero no funciona
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 de jQuery sugieren un complemento para solucionar esto, pero no funciona
Respuestas:
Si src
ya está configurado, entonces el evento se activa en el caso en caché, incluso antes de que el controlador de eventos esté vinculado. Para solucionar esto, puede recorrer la comprobación y desencadenar el evento según .complete
esto:
$("img").one("load", function() {
// do stuff
}).each(function() {
if(this.complete) {
$(this).load(); // For jQuery < 3.0
// $(this).trigger('load'); // For jQuery >= 3.0
}
});
Tenga en cuenta el cambio de .bind()
a .one()
para que el controlador de eventos no se ejecute dos veces.
setTimeout(function(){//do stuff},0)
dentro de la función 'cargar' ... el 0 le da al sistema del navegador (DOM) una marca adicional para garantizar que todo se actualice correctamente.
.load()
no activa el evento y tiene 1 argumento requerido, use .trigger("load")
en su lugar
¿Puedo sugerirle que lo vuelva a cargar en un objeto de imagen que no sea DOM? Si está en caché, esto no tomará tiempo en absoluto, y la carga seguirá disparando. Si no está en caché, disparará la carga cuando se cargue la imagen, que debería ser al mismo tiempo que la versión DOM de la imagen termina de cargarse.
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 el archivo adjunto de carga 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') ;
}) ;
}) ;
load
controlador antes de que se agregue, también esto no funcionará, pero para una imagen, el código OP funciona para muchos :)
#img
es una ID, no un selector de elementos :) También this.src
funciona, no es necesario usar jQuery donde no se necesita :) Pero crear otra imagen parece exagerado en cualquier caso IMO.
imageLoaded
, usetmp.onload = imageLoaded.bind(this)
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);
});
}
});
};
úsalo así:
onImgLoad('img', function(){
// do stuff
});
por ejemplo, para desvanecerse en sus imágenes en carga puede hacer:
$('img').hide();
onImgLoad('img', function(){
$(this).fadeIn(700);
});
O como alternativa, si prefiere 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);
});
width
, max-height
y la licencia height:auto
, a menudo es necesario para establecer la anchura y la altura sólo si es necesario para estirar la imagen; para una solución más robusta, usaría un complemento como ImagesLoaded
¿Realmente tienes que hacerlo con jQuery? También puede adjuntar el onload
evento directamente a su imagen;
<img src="/path/to/image.jpg" onload="doStuff(this);" />
Se disparará cada vez que la imagen se haya cargado, desde caché o no.
onload
controlador cuando la imagen se cargue por segunda vez desde el caché?
También puede usar este código con soporte para errores 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();
}
});
load
primero el controlador y luego llamarlo más tarde en la each
función.
Yo mismo tuve este problema, 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é algo más 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 dónde se rompió antes de que ahora funcione.
Espero eso ayude,
La respuesta aceptada en realidad explica por qué:
Si el src ya está configurado, entonces el evento se dispara en la caja de la caché antes de que el controlador de eventos esté vinculado.
$image.load(function(){ something(); }).attr('src', $image.attr('src'));
restablecer la fuente original.
Al usar jQuery para generar una nueva imagen con el src de la imagen, y asignar el método de carga directamente a eso, se llama con éxito al método de carga cuando jQuery termina de generar la nueva imagen. Esto funciona para mí en IE 8, 9 y 10
$('<img />', {
"src": $("#img").attr("src")
}).load(function(){
// Do something
});
Una solución que encontré https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (Este código se tomó 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;
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');
})
Establezca la fuente antes y después de la carga.
src
antes de adjuntar el onload
controlador, una vez después será suficiente.
Simplemente vuelva a agregar el argumento src en una línea separada después de definir el objeto img. Esto engañará a IE para que active el evento lad. Es feo, pero es la solución más simple que he encontrado hasta ahora.
jQuery('<img/>', {
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:
<div style="position:relative;width:100px;height:100px">
<img src="loading.jpg" style='position:absolute;width:100px;height:100px;z-index:0'/>
<img onLoad="$(this).fadeIn('normal').siblings('img').fadeOut('normal')" src="picture.jpg" style="display:none;position:absolute;width:100px;height:100px;z-index:1"/>
</div>
Si hace eso cuando el navegador almacena imágenes en caché, no hay problema, siempre se muestra la imagen, pero se carga debajo de la imagen real.
Tuve este problema con IE donde 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 debes buscar e.currentTarget.naturalWidth & e.currentTarget.naturalHeight .
Una vez más, IE hace las cosas de manera propia (más complicada).
Puede resolver su problema utilizando el complemento JAIL que también le permite cargar imágenes de manera diferida (mejorando el rendimiento de la página) y pasando la devolución de llamada como parámetro
$('img').asynchImageLoader({callback : function(){...}});
El HTML debería verse así
<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
Si desea una solución CSS pura, este truco funciona muy bien: use 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:
<div class="main_container">
<div class="center_horizontally"></div>
<div class="center_vertically"></div>
<div class="center"></div>
</div>
</div