299

我想要做:

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

但是从缓存中加载图像时不会触发 load 事件。jQuery 文档建议使用插件来解决此问题,但它不起作用

4

14 回答 14

585

如果src已设置,则事件在缓存案例中触发,甚至在您绑定事件处理程序之前。要解决此问题,您可以循环检查并触发基于 off 的事件.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 
  }
});

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

于 2010-10-06T21:34:18.367 回答
53

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

Javascript:

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

更新(以处理多个图像和正确排序的加载附件):

$(document).ready(function() {
    var imageLoaded = function() {
        // Run onload code.
    }
    $('#img').each(function() {
        var tmpImg = new Image() ;
        tmpImg.onload = imageLoaded ;
        tmpImg.src = $(this).attr('src') ;
    }) ;
}) ;
于 2010-10-06T21:33:32.140 回答
41

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

/**
 * 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);
            });
        }
    });
};

像这样使用它:

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

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

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

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

并以这种方式使用它:

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

例如:

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});
于 2013-12-03T12:20:23.670 回答
23

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

<img src="/path/to/image.jpg" onload="doStuff(this);" />

每次图像加载时都会触发,无论是否从缓存中加载。

于 2010-10-06T21:34:00.877 回答
16

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

$("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();
    }
});
于 2014-03-20T10:54:38.413 回答
13

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

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

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

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

我不知道它为什么会起作用,但我已经在 IE7 上对其进行了测试,并且在它现在起作用之前它在哪里坏了。

希望能帮助到你,

编辑

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

如果 src 已经设置,那么在绑定事件处理程序之前,事件会在缓存中触发。

于 2012-12-13T13:29:01.450 回答
5

通过jQuery使用图片的src生成一张新图片,并直接给它赋值load方法,当jQuery完成生成新图片时,load方法就成功调用了。这在 IE 8、9 和 10 中对我有用

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});
于 2013-06-24T17:10:41.270 回答
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;
于 2017-06-22T14:01:48.923 回答
4

对 GUS 示例的修改:

$(document).ready(function() {
    var tmpImg = new Image() ;
    tmpImg.onload = function() {
        // Run onload code.
    } ;

tmpImg.src = $('#img').attr('src');
})

在onload之前和之后设置源。

于 2010-10-06T21:36:29.483 回答
3

只需在定义 img 对象后在单独的行上重新添加 src 参数即可。这将诱使 IE 触发小伙子事件。它很丑陋,但它是迄今为止我发现的最简单的解决方法。

jQuery('<img/>', {
    src: url,
    id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE
于 2013-11-14T15:59:01.270 回答
1

如果您想这样做,我可以给您一些提示:

<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>

如果你在浏览器缓存图片时这样做,总是显示img但在真实图片下加载img是没有问题的。

于 2012-02-13T03:10:44.493 回答
1

我在 IE 中遇到了这个问题,其中 e.target.width 未定义。load 事件会触发,但我无法在 IE 中获得图像的尺寸(chrome + FF 有效)。

原来你需要寻找e.currentTarget.naturalWidth & e.currentTarget.naturalHeight

再一次,IE 以自己(更复杂)的方式做事。

于 2012-10-12T08:04:02.410 回答
0

您可以使用JAIL插件解决您的问题,该插件还允许您延迟加载图像(提高页面性能)并将回调作为参数传递

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

HTML 应该看起来像

<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
于 2011-01-09T10:17:05.197 回答
-1

如果你想要一个纯 CSS 解决方案,这个技巧非常有效 - 使用变换对象。无论是否缓存图像,这也适用于图像:

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

代码笔示例

Codepen LESS 示例

于 2016-06-10T18:35:44.173 回答