图像加载时的 jQuery 回调(即使图像已缓存)

发布于 2024-09-26 13:32:10 字数 401 浏览 5 评论 0原文

我想做:

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

但是从缓存加载图像时不会触发加载事件。 jQuery 文档 建议一个插件 可以解决这个问题,但是 它不起作用

I want to do:

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

But the load event doesn't fire when the image is loaded from cache. The jQuery docs suggest a plugin to fix this, but it doesn't work

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

梓梦 2024-10-03 13:32:10

如果 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 
  }
});

注意 .bind()。 one() 因此事件处理程序不会运行两次。

If the src is already set, then the event is firing in the cached case, before you even get the event handler bound. To fix this, you can loop through checking and triggering the event based off .complete, like this:

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

Note the change from .bind() to .one() so the event handler doesn't run twice.

小糖芽 2024-10-03 13:32:10

我可以建议你将它重新加载到非 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') ;
    }) ;
}) ;

Can I suggest that you reload it into a non-DOM image object? If it's cached, this will take no time at all, and the onload will still fire. If it isn't cached, it will fire the onload when the image is loaded, which should be the same time as the DOM version of the image finishes loading.

Javascript:

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

Updated (to handle multiple images and with correctly ordered onload attachment):

$(document).ready(function() {
    var imageLoaded = function() {
        // Run onload code.
    }
    $('#img').each(function() {
        var tmpImg = new Image() ;
        tmpImg.onload = imageLoaded ;
        tmpImg.src = $(this).attr('src') ;
    }) ;
}) ;
有木有妳兜一样 2024-10-03 13:32:10

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

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

My simple solution, it doesn't need any external plugin and for common cases should be enough:

/**
 * 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 it like this:

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

for example, to fade in your images on load you can do:

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

Or as alternative, if you prefer a jquery plugin-like approach:

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

and use it in this way:

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

for example:

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});
幸福还没到 2024-10-03 13:32:10

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

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

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

Do you really have to do it with jQuery? You can attach the onload event directly to your image as well;

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

It will fire every time the image has loaded, from cache or not.

寄与心 2024-10-03 13:32:10

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

$("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();
    }
});

You can also use this code with support for loading error:

$("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();
    }
});
雪花飘飘的天空 2024-10-03 13:32:10

我自己也遇到了这个问题,到处搜索不涉及终止缓存或下载插件的解决方案。

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

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

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

我不知道它为什么能工作,但我已经在 IE7 上测试了它,以及它在现在工作之前在哪里崩溃了。

希望它有帮助,

编辑

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

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

I just had this problem myself, searched everywhere for a solution that didn't involve killing my cache or downloading a plugin.

I didn't see this thread immediately so I found something else instead which is an interesting fix and (I think) worthy of posting here:

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

I actually got this idea from the comments here: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

I have no idea why it works but I have tested this on IE7 and where it broke before it now works.

Hope it helps,

Edit

The accepted answer actually explains why:

If the src is already set then the event is firing in the cache cased before you get the event handler bound.

飘逸的'云 2024-10-03 13:32:10

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

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

By using jQuery to generate a new image with the image's src, and assigning the load method directly to that, the load method is successfully called when jQuery finishes generating the new image. This is working for me in IE 8, 9 and 10

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});
阪姬 2024-10-03 13:32:10

我找到的解决方案 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;

A solution I found https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12
(This code taken directly from the comment)

var photo = document.getElementById('image_id');
var img = new Image();
img.addEventListener('load', myFunction, false);
img.src = 'http://newimgsource.jpg';
photo.src = img.src;
分開簡單 2024-10-03 13:32:10

对GUS示例的修改:

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

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

在onload之前和之后设置源。

A modification to GUS's example:

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

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

Set the source before and after the onload.

甜嗑 2024-10-03 13:32:10

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

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

Just re-add the src argument on a separate line after the img oject is defined. This will trick IE into triggering the lad-event. It is ugly, but it is the simplest workaround I've found so far.

jQuery('<img/>', {
    src: url,
    id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE
桃气十足 2024-10-03 13:32:10

如果你想这样做,我可以给你一个小提示:

<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是没有问题的。

I can give you a little tip if you want do like this:

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

If you do that when the browser caches pictures, it's no problem always img shown but loading img under real picture.

戏剧牡丹亭 2024-10-03 13:32:10

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

事实证明,您需要寻找 e.currentTarget.naturalWidth & e.currentTarget.naturalHeight

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

I had this problem with IE where the e.target.width would be undefined. The load event would fire but I couldn't get the dimensions of the image in IE (chrome + FF worked).

Turns out you need to look for e.currentTarget.naturalWidth & e.currentTarget.naturalHeight.

Once again, IE does things it's own (more complicated) way.

绿光 2024-10-03 13:32:10

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

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

HTML 应该如下所示

<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />

You can solve your problem using JAIL plugin that also allows you to lazy load images (improving the page performance) and passing the callback as parameter

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

The HTML should look like

<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
憧憬巴黎街头的黎明 2024-10-03 13:32:10

如果你想要一个纯 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 示例

Codepen LESS 示例

If you want a pure CSS solution, this trick works very well - use the transform object. This also works with images when they're cached or not:

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 example

Codepen LESS example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文