jQuery回调图像加载(即使图像被缓存)

Tom*_*man 282 jquery image jquery-load jquery-events

我想要做:

$("img").bind('load', function() {
  // do stuff
});
Run Code Online (Sandbox Code Playgroud)

但是从缓存加载图像时不会触发加载事件.jQuery文档提出了一个修复此问题的插件,但它不起作用

Nic*_*ver 561

如果src已经设置了,那么在你甚至绑定事件处理程序之前,事件就会在缓存的情况下触发.要解决此问题,您可以循环检查并基于.complete此触发事件,如下所示:

$("img").one("load", function() {
  // do stuff
}).each(function() {
  if(this.complete) {
      $(this).load(); // For jQuery < 3.0 
      // $(this).trigger('load'); // For jQuery >= 3.0 
  }
});
Run Code Online (Sandbox Code Playgroud)

请注意从更改为.bind(),.one()因此事件处理程序不会运行两次.

  • 既然你的答案已经改变了.现在有一个**小工作插件[jQuery.imagesLoaded](https://github.com/desandro/imagesloaded)**.他们修复了所有[小浏览器怪癖](https://github.com/desandro/imagesloaded/wiki/Browser-quirks). (32认同)
  • @Lode - 这是一个巨大的插件,任何规模都不小! (14认同)
  • 你的解决方案对我来说非常合适,但我希望了解一些内容,当这些代码"if(this.complete)"将在图像内容加载之后或之前运行时?因为我可以从中了解到这一点.你正在循环所有的$("img")并且可能是图像内容是空的并且负载不会发生.嗯,我想我有一些缺失的东西,如果你可以描述的话会更好地理解它会很好.谢谢. (8认同)
  • 因为JQuery 3方法`.load()`不触发事件并且有1个必需参数,所以使用`.trigger("load")` (5认同)
  • 我会在'load'函数中添加一个`setTimeout(function(){// do stuff},0)`******给浏览器系统(DOM)一个额外的滴答以确保一切都是适当更新. (2认同)

Gus*_*Gus 45

我可以建议您将其重新加载到非DOM图像对象中吗?如果它被缓存,这将花费任何时间,并且onload仍将触发.如果它没有被缓存,它将在加载图像时触发onload,这应该与图像的DOM版本完成加载的时间相同.

使用Javascript:

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

更新(处理多个图像并使用正确订购的onload附件):

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

  • `$('#img').每个(`?那里的东西非常错误 (10认同)

gua*_*ari 38

我的简单解决方案,它不需要任何外部插件,对于常见情况应该足够了:

/**
 * 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);
            });
        }
    });
};
Run Code Online (Sandbox Code Playgroud)

像这样用它:

onImgLoad('img', function(){
    // do stuff
});
Run Code Online (Sandbox Code Playgroud)

例如,要在加载时淡入图像,您可以执行以下操作:

$('img').hide();
onImgLoad('img', function(){
    $(this).fadeIn(700);
});
Run Code Online (Sandbox Code Playgroud)

或者作为替代方案,如果您更喜欢类似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);
Run Code Online (Sandbox Code Playgroud)

并以这种方式使用它:

$('img').imgLoad(function(){
    // do stuff
});
Run Code Online (Sandbox Code Playgroud)

例如:

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});
Run Code Online (Sandbox Code Playgroud)


Bjö*_*örn 23

你真的必须用jQuery吗?您也可以将onload事件直接附加到图像上;

<img src="/path/to/image.jpg" onload="doStuff(this);" />
Run Code Online (Sandbox Code Playgroud)

每次加载图像时都会触发,无论是否从高速缓存加载.

  • 没有内联JavaScript,它更干净 (5认同)
  • 老兄,你救了我的命,我已经尝试了至少十几个其他的解决方案,你的是唯一真正有效的解决方案.我正在认真考虑再创建10个帐户,将你的答案再投10次.真的,谢谢! (3认同)

Pio*_*ski 15

您也可以使用此代码支持加载错误:

$("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();
    }
});
Run Code Online (Sandbox Code Playgroud)


Sam*_*aye 13

我自己就遇到了这个问题,到处寻找一个不涉及杀死我的缓存或下载插件的解决方案.

我没有立即看到这个帖子所以我找到了别的东西,而这是一个有趣的修复,并且(我认为)值得在这里发帖:

$('.image').load(function(){
    // stuff
}).attr('src', 'new_src');
Run Code Online (Sandbox Code Playgroud)

我实际上从这里的评论中得到了这个想法:http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

我不知道为什么它可以工作,但我已经在IE7上测试了它,并且在它现在可以工作之前它已经破坏了.

希望能帮助到你,

编辑

接受的答案实际上解释了原因:

如果已经设置了src,则在绑定事件处理程序之前,事件将在缓存中触发.

  • 我已经在很多浏览器中测试过,并且没有发现它在任何地方都失败了.我使用`$ image.load(function(){something();}).attr('src',$ image.attr('src'));`来重置原始源. (4认同)

小智 5

通过使用jQuery使用图像的src生成新图像,并直接为其分配load方法,当jQuery完成生成新图像时,将成功调用load方法。这在IE 8、9和10中为我工作

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});
Run Code Online (Sandbox Code Playgroud)


All*_*onC 5

我找到了一个解决方案https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (此代码直接从注释中获取)

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