Eu quero fazer:
$("img").bind('load', function() {
// do stuff
});
Mas o evento load não dispara quando a imagem é carregada do cache. Os documentos do jQuery sugerem um plugin para corrigir isso, mas não funciona
Eu quero fazer:
$("img").bind('load', function() {
// do stuff
});
Mas o evento load não dispara quando a imagem é carregada do cache. Os documentos do jQuery sugerem um plugin para corrigir isso, mas não funciona
Respostas:
Se o src
já estiver definido, o evento será disparado no caso em cache, antes mesmo de você vincular o manipulador de eventos. Para corrigir isso, você pode percorrer a verificação e o acionamento do evento com base .complete
, assim:
$("img").one("load", function() {
// do stuff
}).each(function() {
if(this.complete) {
$(this).load(); // For jQuery < 3.0
// $(this).trigger('load'); // For jQuery >= 3.0
}
});
Observe a alteração de .bind()
para .one()
para que o manipulador de eventos não seja executado duas vezes.
setTimeout(function(){//do stuff},0)
dentro da função 'carregar' ... o 0 dá ao sistema do navegador (DOM) uma marca extra para garantir que tudo seja atualizado corretamente.
.load()
não faz evento de disparo e tem um argumento necessário, utilizar .trigger("load")
em vez disso
Posso sugerir que você o recarregue em um objeto de imagem que não seja do DOM? Se estiver armazenado em cache, isso não levará tempo e a carga ainda será acionada. Se não estiver armazenado em cache, disparará a carga quando a imagem for carregada, que deve ser a mesma hora que a versão DOM da imagem termina o carregamento.
Javascript:
$(document).ready(function() {
var tmpImg = new Image() ;
tmpImg.src = $('#img').attr('src') ;
tmpImg.onload = function() {
// Run onload code.
} ;
}) ;
Atualizado (para lidar com várias imagens e com o anexo onload ordenado corretamente):
$(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
manipulador antes de adicioná-lo, mas isso não funcionará, mas para uma imagem, o código de OP funciona para muitos :)
#img
é um ID, não um seletor de elementos :) Também this.src
funciona, não é necessário usar o jQuery onde não é necessário :) Mas criar outra imagem parece exagerar nos dois casos IMO.
imageLoaded
, usetmp.onload = imageLoaded.bind(this)
Minha solução simples, ele não precisa de nenhum plugin externo e, para casos comuns, deve 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);
});
}
});
};
use-o assim:
onImgLoad('img', function(){
// do stuff
});
por exemplo, para desbotar suas imagens no carregamento, você pode:
$('img').hide();
onImgLoad('img', function(){
$(this).fadeIn(700);
});
Ou, como alternativa, se você preferir uma abordagem semelhante ao plugin 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);
e use-o desta maneira:
$('img').imgLoad(function(){
// do stuff
});
por exemplo:
$('img').hide().imgLoad(function(){
$(this).fadeIn(700);
});
width
, max-height
e licença height:auto
, muitas vezes é necessário para definir a largura e altura apenas se você precisa para esticar a imagem; para uma solução mais robusta eu iria usar um plugin como ImagesLoaded
Você realmente tem que fazer isso com o jQuery? Você também pode anexar o onload
evento diretamente à sua imagem;
<img src="/path/to/image.jpg" onload="doStuff(this);" />
Ele dispara toda vez que a imagem é carregada, do cache ou não.
onload
manipulador será acionado quando a imagem for carregada uma segunda vez do cache?
Você também pode usar este código com suporte para erro de carregamento:
$("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
manipulador primeiro e depois chamá-lo mais tarde na each
função.
Eu mesmo tive esse problema, procurei em todos os lugares uma solução que não envolvesse matar meu cache ou baixar um plugin.
Eu não vi esse tópico imediatamente, então encontrei outra coisa que é uma correção interessante e (acho) digna de ser postada aqui:
$('.image').load(function(){
// stuff
}).attr('src', 'new_src');
Na verdade, recebi essa idéia dos comentários aqui: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/
Eu não tenho idéia do por que ele funciona, mas eu testei isso no IE7 e onde ele quebrou antes de agora funcionar.
Espero que ajude,
A resposta aceita realmente explica o porquê:
Se o src já estiver definido, o evento será disparado no cache fornecido antes de você vincular o manipulador de eventos.
$image.load(function(){ something(); }).attr('src', $image.attr('src'));
redefinir a fonte original.
Usando o jQuery para gerar uma nova imagem com o src da imagem e atribuindo o método de carregamento diretamente a ele, o método de carregamento é chamado com êxito quando o jQuery termina de gerar a nova imagem. Isso está funcionando para mim no IE 8, 9 e 10
$('<img />', {
"src": $("#img").attr("src")
}).load(function(){
// Do something
});
Uma solução que encontrei https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (este código foi extraído diretamente do comentário)
var photo = document.getElementById('image_id');
var img = new Image();
img.addEventListener('load', myFunction, false);
img.src = 'http://newimgsource.jpg';
photo.src = img.src;
Uma modificação no exemplo da GUS:
$(document).ready(function() {
var tmpImg = new Image() ;
tmpImg.onload = function() {
// Run onload code.
} ;
tmpImg.src = $('#img').attr('src');
})
Defina a fonte antes e depois da carga.
src
antes de anexar o onload
manipulador, uma vez que depois será suficiente.
Apenas adicione novamente o argumento src em uma linha separada após a definição do objeto. Isso levará o IE a acionar o evento lad. É feio, mas é a solução mais simples que encontrei até agora.
jQuery('<img/>', {
src: url,
id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE
Posso dar uma pequena dica, se você quiser fazer o seguinte:
<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>
Se você fizer isso quando o navegador armazena em cache as imagens, não há problema em sempre mostrar o img, mas carregar o img na imagem real.
Eu tive esse problema com o IE, onde a largura de e.target.windth seria indefinida. O evento de carregamento seria acionado, mas não consegui obter as dimensões da imagem no IE (chrome + FF funcionou).
Acontece que você precisa procurar por e.currentTarget.naturalWidth e e.currentTarget.naturalHeight .
Mais uma vez, o IE faz as coisas de maneira própria (mais complicada).
Você pode resolver seu problema usando o plug-in JAIL, que também permite carregar imagens com preguiça (melhorando o desempenho da página) e passando o retorno de chamada como parâmetro
$('img').asynchImageLoader({callback : function(){...}});
O HTML deve se parecer com
<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
Se você deseja uma solução CSS pura, esse truque funciona muito bem - use o objeto de transformação. Isso também funciona com imagens quando elas são armazenadas em cache ou não:
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