与浏览器无关的方式来检测何时加载图像

时间:2021-06-24 00:00:50

In IE, you can onreadystatechange. There's onload, but I read scary things. jQuery wraps up the DOM's load event quite nicely with "ready". It seems likely I am just ignorant of another nice library's implementation of image loading.

在IE中,您可以onreadystatechange。有载入,但我读了可怕的东西。 jQuery用“就绪”很好地包装了DOM的加载事件。我似乎只是不知道另一个很好的库的图像加载实现。

The context is that I am generating images dynamically (via server callbacks) that can take some time download. In my IE-only code I set the src of the img element, then when the onreadystatechange event fires with the "complete" status, I add it to the DOM so the user sees it.

上下文是我动态生成图像(通过服务器回调),可能需要一些时间下载。在我的IE-only代码中,我设置了img元素的src,然后当onreadystatechange事件以“完成”状态触发时,我将它添加到DOM,以便用户看到它。

I'd be happy with a "native" JavaScript solution, or a pointer to a library that does the work. There's so many libraries out there and I'm sure this is a case of me just not knowing about the right one. That said, we're already jQuery users, so I'm not eager to add a very large library just to get this functionality.

我对“本机”JavaScript解决方案或指向完成工作的库的指针感到满意。那里有很多图书馆,我确信这是我不知道正确的图书馆的情况。也就是说,我们已经是jQuery用户了,所以我并不急于为了获得这个功能而添加一个非常大的库。

9 个解决方案

#1


46  

NOTE: I wrote this in 2010, the browsers in the wild were IE 8/9 beta, Firefox 3.x, and Chrome 4.x. Please use this for research purposes only, I doubt you could copy/paste this into a modern browser and have it work without issue.

注意:我在2010年写了这个,浏览器是IE 8/9 beta,Firefox 3.x和Chrome 4.x.请将此用于研究目的,我怀疑您可以将其复制/粘贴到现代浏览器中并使其正常工作。

WARNING: It is 2017 now I still get points on this now and then, please only use this for research purposes. I currently have no idea how to detect image loading status, but there are probably much more graceful ways of doing it than this... at least I seriously hope there are. I highly recommend NOT using my code in a production environment without more research.

警告:现在是2017年,我现在仍然可以获得积分,请仅将其用于研究目的。我目前不知道如何检测图像加载状态,但有可能比这更优雅的方式...至少我真的希望有。我强烈建议不要在生产环境中使用我的代码而不进行更多研究。


I'm a bit late to this party, maybe this answer will help someone else...

我参加这个派对有点晚了,也许这个答案会帮助别人......

If you're using jQuery don't bother with the stock event handlers (onclick/onmouseover/etc), actually just stop using them altogether. Use the event methods they provided in their API.

如果你正在使用jQuery,请不要理会股票事件处理程序(onclick / onmouseover / etc),实际上只是完全停止使用它们。使用他们在API中提供的事件方法。


This will alert, before the image is appended to the body, because load event is triggered when the image is loaded into memory. It is doing exactly what you tell it to: create an image with the src of test.jpg, when test.jpg loads do an alert, then append it to the body.

这将在图像附加到正文之前发出警报,因为在将图像加载到内存时会触发加载事件。它正是你告诉它的:用test.jpg的src创建一个图像,当test.jpg加载做一个警报,然后将它附加到正文。

var img = $('<img src="test.jpg" />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);

This will alert, after the image is inserted into the body, again, doing what you told it to: create an image, set an event (no src set, so it hasn't loaded), append the image to the body (still no src), now set the src... now the image is loaded so the event is triggered.

这将在图像插入到身体后再次发出警报,执行您告诉它的操作:创建图像,设置事件(没有设置src,因此没有加载),将图像附加到身体上(仍然没有src),现在设置src ...现在加载图像以便触发事件。

var img = $('<img />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);
$img.attr('src','test.jpg');

You can of course also add an error handler and merge a bunch of events using bind().

您当然也可以添加错误处理程序并使用bind()合并一堆事件。

var img = $('<img />');
img.bind({
    load: function() {
        alert('Image loaded.');
    },
    error: function() {
        alert('Error thrown, image didn\'t load, probably a 404.');
    }
});
$('body').append(img);
img.attr('src','test.jpg');

Per the request by @ChrisKempen ...

根据@ChrisKempen的要求......

Here is a non-event driven way of determining if the images are broken after the DOM is loaded. This code is a derivative of code from an article by StereoChrome which uses naturalWidth, naturalHeight, and complete attributes to determine if the image exists.

这是一种非事件驱动的方法,用于确定在加载DOM之后图像是否被破坏。此代码是StereoChrome文章中代码的衍生物,它使用naturalWidth,naturalHeight和完整属性来确定图像是否存在。

$('img').each(function() {
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) {
        alert('broken image');
    }
});

#2


10  

According to the W3C spec, only the BODY and FRAMESET elements provide an "onload" event to attach to. Some browsers support it regardless, but just be aware that it is not required to implement the W3C spec.

根据W3C规范,只有BODY和FRAMESET元素提供附加的“onload”事件。有些浏览器无论如何都支持它,但请注意,不需要实现W3C规范。

Something that might be pertinent to this discussion, though not necessarily the answer you are in need of, is this discussion:

可能与此讨论相关的事情,但不一定是您需要的答案,是这个讨论:

Image.onload event does not fire on Internet Explorer when image is in cache

当图像在缓存中时,Image.onload事件不会在Internet Explorer上触发


Something else that may be related to your needs, though it may not, is this info on supporting a synthesized "onload" event for any dynamically-loaded DOM element:

可能与您的需求相关的其他东西,虽然它可能不是,这个信息支持任何动态加载的DOM元素的合成“onload”事件:

How can I determine if a dynamically-created DOM element has been added to the DOM?

如何确定是否已将动态创建的DOM元素添加到DOM中?

#3


5  

The only reliable way I've found is to do it all on the client-side like this...

我发现唯一可靠的方法是在客户端这样做,就像这样......

var img = new Image();
img.onload = function() {
  alert('Done!');
}
img.src = '/images/myImage.jpg';

#4


3  

I think onload should work fine. Do you have to generate the markup for the images, or can you add them statically? If the latter, I'd suggest the following:

我认为onload应该可以正常工作。您是否必须为图像生成标记,还是可以静态添加它们?如果是后者,我建议如下:

<img src="foo.png" class="classNeededToHideImage" onload="makeVisible(this)">

Alternatively, you can use window.onload to make all images visible at once - window.onload fires after all external ressources have finished loading.

或者,您可以使用window.onload立即显示所有图像 - window.onload在所有外部资源完成加载后触发。

If you want to add the images dynamically, you first have to wait for the DOM to be ready to be modified, ie use jQuery or implement your own DOMContentLoaded hack for browsers which don't support it natively.

如果要动态添加图像,首先必须等待DOM准备好被修改,即使用jQuery或为本机不支持它的浏览器实现自己的DOMContentLoaded hack。

Then, you create your image objects, assign onload listeners to make them visible and/or add them to the document.

然后,您可以创建图像对象,分配onload侦听器以使其可见和/或将它们添加到文档中。

Even better (but slightly more complicated) would be to create and start loading the images immediately when the script executes. On DOMContentLoaded, you'll have to check each image for complete to decide whether to add them immediately to the document or wait for the image's onload listener to fire.

更好(但稍微复杂一点)就是在脚本执行时立即创建并开始加载图像。在DOMContentLoaded上,您必须检查每个图像是否完整,以决定是将它们立即添加到文档还是等待图像的onload侦听器触发。

#5


3  

Okay, I'll try to summarize the various partial answers here (including mine).

好的,我将尝试总结这里的各种部分答案(包括我的)。

It would appear the answer is to use onload, which is "widely supported" though not officially required according to standards. Note that for IE in particular, you must set onLoad before setting the src attribute or it may not fire onload when loading an image from the cache. This seems like best practice in any case: set up your event handlers before you start firing events. Where onload is not supported, one should assume that the functionality simply isn't available.

似乎答案是使用onload,虽然根据标准没有正式要求,但是“广泛支持”。请注意,特别是对于IE,您必须在设置src属性之前设置onLoad,否则在从缓存加载图像时可能不会触发onload。在任何情况下,这似乎都是最佳实践:在开始触发事件之前设置事件处理程序。如果不支持onload,则应该假设功能根本不可用。

#6


1  

It would appear the answer is use onreadystatechange in IE, and onLoad in other browsers. If neither one is available, do something else. onLoad would be preferable, but IE doesn't fire it when loading an image from the cache, as noted in one of the answers below.

似乎答案是在IE中使用onreadystatechange,在其他浏览器中使用onLoad。如果两者都不可用,请做其他事情。 onLoad会更好,但IE从缓存中加载图像时不会触发它,如下面的答案中所述。

#7


1  

If im not mistaken in javascript an image tag has the events onload and onerror

如果我没有在javascript中出错,那么图片标签会有事件onload和onerror

here is an intersting bit of code i did to hide broken images

这是我用来隐藏破碎图像的一段代码

in a style tag

在样式标签中

img.failed{
   display:none;
}

using the img onerror i had a piece of javascript that did this.className=failed and it would hide the image if it errored

使用img onerror我有一段javascript做了this.className =失败,它会隐藏图像,如果它错误

however i may have misunderstood what your goal

但是我可能误解了你的目标

#8


1  

HTML

HTML

<img id="myimage" src="http://farm4.static.flickr.com/3106/2819995451_23db3f25fe_t.jpg"/>​

SCRIPT

脚本

setTimeout(function(){
    $('#myimage').attr('src','http://cdn.redmondpie.com/wp-content/uploads/2011/05/canarylogo.png').load(function(){
        alert('Main Image Loaded');

        $('#myimage').attr('src','image.jpg').bind({
            load: function(){
                alert('Image loaded.');
            },
            error: function(){
                alert('Image not loaded.');
            }
        });
    });
},1000);

JS Fiddle

JS小提琴

http://jsfiddle.net/gerst20051/sLge3/

http://jsfiddle.net/gerst20051/sLge3/

#9


0  

Using a data URI is the way to go. However, using an SVG instead of a GIF provides more flexibility. You can quickly change the size. Just run this in a JavaScript console:

使用数据URI是可行的方法。但是,使用SVG而不是GIF可提供更大的灵活性。您可以快速更改大小。只需在JavaScript控制台中运行:

var width = 1;
var height = 1;
'data:image/svg+xml;base64,' +
btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"/>`);

Example output:

输出示例:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz4=

I threw together a quick CodePen utility to create transparent SVGs with arbitrary dimensions. It's pretty basic, so you'll need to modify it if you want to add color or other features to the image.

我将一个快速CodePen实用程序拼凑在一起,以创建具有任意维度的透明SVG。它非常基本,因此如果要为图像添加颜色或其他功能,则需要对其进行修改。

The biggest advantage over a single-pixel image is that it allows aspect ratio to be preserved. This is important for dynamically-sized images, as layout is often performed before the src changes to a real image (if that's the intended purpose). Until the src changes, image will be square, which may be undesirable.

单像素图像的最大优势在于它可以保留纵横比。这对于动态大小的图像很重要,因为布局通常在src更改为真实图像之前执行(如果这是预期目的)。直到src改变,图像将是方形的,这可能是不合需要的。

#1


46  

NOTE: I wrote this in 2010, the browsers in the wild were IE 8/9 beta, Firefox 3.x, and Chrome 4.x. Please use this for research purposes only, I doubt you could copy/paste this into a modern browser and have it work without issue.

注意:我在2010年写了这个,浏览器是IE 8/9 beta,Firefox 3.x和Chrome 4.x.请将此用于研究目的,我怀疑您可以将其复制/粘贴到现代浏览器中并使其正常工作。

WARNING: It is 2017 now I still get points on this now and then, please only use this for research purposes. I currently have no idea how to detect image loading status, but there are probably much more graceful ways of doing it than this... at least I seriously hope there are. I highly recommend NOT using my code in a production environment without more research.

警告:现在是2017年,我现在仍然可以获得积分,请仅将其用于研究目的。我目前不知道如何检测图像加载状态,但有可能比这更优雅的方式...至少我真的希望有。我强烈建议不要在生产环境中使用我的代码而不进行更多研究。


I'm a bit late to this party, maybe this answer will help someone else...

我参加这个派对有点晚了,也许这个答案会帮助别人......

If you're using jQuery don't bother with the stock event handlers (onclick/onmouseover/etc), actually just stop using them altogether. Use the event methods they provided in their API.

如果你正在使用jQuery,请不要理会股票事件处理程序(onclick / onmouseover / etc),实际上只是完全停止使用它们。使用他们在API中提供的事件方法。


This will alert, before the image is appended to the body, because load event is triggered when the image is loaded into memory. It is doing exactly what you tell it to: create an image with the src of test.jpg, when test.jpg loads do an alert, then append it to the body.

这将在图像附加到正文之前发出警报,因为在将图像加载到内存时会触发加载事件。它正是你告诉它的:用test.jpg的src创建一个图像,当test.jpg加载做一个警报,然后将它附加到正文。

var img = $('<img src="test.jpg" />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);

This will alert, after the image is inserted into the body, again, doing what you told it to: create an image, set an event (no src set, so it hasn't loaded), append the image to the body (still no src), now set the src... now the image is loaded so the event is triggered.

这将在图像插入到身体后再次发出警报,执行您告诉它的操作:创建图像,设置事件(没有设置src,因此没有加载),将图像附加到身体上(仍然没有src),现在设置src ...现在加载图像以便触发事件。

var img = $('<img />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);
$img.attr('src','test.jpg');

You can of course also add an error handler and merge a bunch of events using bind().

您当然也可以添加错误处理程序并使用bind()合并一堆事件。

var img = $('<img />');
img.bind({
    load: function() {
        alert('Image loaded.');
    },
    error: function() {
        alert('Error thrown, image didn\'t load, probably a 404.');
    }
});
$('body').append(img);
img.attr('src','test.jpg');

Per the request by @ChrisKempen ...

根据@ChrisKempen的要求......

Here is a non-event driven way of determining if the images are broken after the DOM is loaded. This code is a derivative of code from an article by StereoChrome which uses naturalWidth, naturalHeight, and complete attributes to determine if the image exists.

这是一种非事件驱动的方法,用于确定在加载DOM之后图像是否被破坏。此代码是StereoChrome文章中代码的衍生物,它使用naturalWidth,naturalHeight和完整属性来确定图像是否存在。

$('img').each(function() {
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) {
        alert('broken image');
    }
});

#2


10  

According to the W3C spec, only the BODY and FRAMESET elements provide an "onload" event to attach to. Some browsers support it regardless, but just be aware that it is not required to implement the W3C spec.

根据W3C规范,只有BODY和FRAMESET元素提供附加的“onload”事件。有些浏览器无论如何都支持它,但请注意,不需要实现W3C规范。

Something that might be pertinent to this discussion, though not necessarily the answer you are in need of, is this discussion:

可能与此讨论相关的事情,但不一定是您需要的答案,是这个讨论:

Image.onload event does not fire on Internet Explorer when image is in cache

当图像在缓存中时,Image.onload事件不会在Internet Explorer上触发


Something else that may be related to your needs, though it may not, is this info on supporting a synthesized "onload" event for any dynamically-loaded DOM element:

可能与您的需求相关的其他东西,虽然它可能不是,这个信息支持任何动态加载的DOM元素的合成“onload”事件:

How can I determine if a dynamically-created DOM element has been added to the DOM?

如何确定是否已将动态创建的DOM元素添加到DOM中?

#3


5  

The only reliable way I've found is to do it all on the client-side like this...

我发现唯一可靠的方法是在客户端这样做,就像这样......

var img = new Image();
img.onload = function() {
  alert('Done!');
}
img.src = '/images/myImage.jpg';

#4


3  

I think onload should work fine. Do you have to generate the markup for the images, or can you add them statically? If the latter, I'd suggest the following:

我认为onload应该可以正常工作。您是否必须为图像生成标记,还是可以静态添加它们?如果是后者,我建议如下:

<img src="foo.png" class="classNeededToHideImage" onload="makeVisible(this)">

Alternatively, you can use window.onload to make all images visible at once - window.onload fires after all external ressources have finished loading.

或者,您可以使用window.onload立即显示所有图像 - window.onload在所有外部资源完成加载后触发。

If you want to add the images dynamically, you first have to wait for the DOM to be ready to be modified, ie use jQuery or implement your own DOMContentLoaded hack for browsers which don't support it natively.

如果要动态添加图像,首先必须等待DOM准备好被修改,即使用jQuery或为本机不支持它的浏览器实现自己的DOMContentLoaded hack。

Then, you create your image objects, assign onload listeners to make them visible and/or add them to the document.

然后,您可以创建图像对象,分配onload侦听器以使其可见和/或将它们添加到文档中。

Even better (but slightly more complicated) would be to create and start loading the images immediately when the script executes. On DOMContentLoaded, you'll have to check each image for complete to decide whether to add them immediately to the document or wait for the image's onload listener to fire.

更好(但稍微复杂一点)就是在脚本执行时立即创建并开始加载图像。在DOMContentLoaded上,您必须检查每个图像是否完整,以决定是将它们立即添加到文档还是等待图像的onload侦听器触发。

#5


3  

Okay, I'll try to summarize the various partial answers here (including mine).

好的,我将尝试总结这里的各种部分答案(包括我的)。

It would appear the answer is to use onload, which is "widely supported" though not officially required according to standards. Note that for IE in particular, you must set onLoad before setting the src attribute or it may not fire onload when loading an image from the cache. This seems like best practice in any case: set up your event handlers before you start firing events. Where onload is not supported, one should assume that the functionality simply isn't available.

似乎答案是使用onload,虽然根据标准没有正式要求,但是“广泛支持”。请注意,特别是对于IE,您必须在设置src属性之前设置onLoad,否则在从缓存加载图像时可能不会触发onload。在任何情况下,这似乎都是最佳实践:在开始触发事件之前设置事件处理程序。如果不支持onload,则应该假设功能根本不可用。

#6


1  

It would appear the answer is use onreadystatechange in IE, and onLoad in other browsers. If neither one is available, do something else. onLoad would be preferable, but IE doesn't fire it when loading an image from the cache, as noted in one of the answers below.

似乎答案是在IE中使用onreadystatechange,在其他浏览器中使用onLoad。如果两者都不可用,请做其他事情。 onLoad会更好,但IE从缓存中加载图像时不会触发它,如下面的答案中所述。

#7


1  

If im not mistaken in javascript an image tag has the events onload and onerror

如果我没有在javascript中出错,那么图片标签会有事件onload和onerror

here is an intersting bit of code i did to hide broken images

这是我用来隐藏破碎图像的一段代码

in a style tag

在样式标签中

img.failed{
   display:none;
}

using the img onerror i had a piece of javascript that did this.className=failed and it would hide the image if it errored

使用img onerror我有一段javascript做了this.className =失败,它会隐藏图像,如果它错误

however i may have misunderstood what your goal

但是我可能误解了你的目标

#8


1  

HTML

HTML

<img id="myimage" src="http://farm4.static.flickr.com/3106/2819995451_23db3f25fe_t.jpg"/>​

SCRIPT

脚本

setTimeout(function(){
    $('#myimage').attr('src','http://cdn.redmondpie.com/wp-content/uploads/2011/05/canarylogo.png').load(function(){
        alert('Main Image Loaded');

        $('#myimage').attr('src','image.jpg').bind({
            load: function(){
                alert('Image loaded.');
            },
            error: function(){
                alert('Image not loaded.');
            }
        });
    });
},1000);

JS Fiddle

JS小提琴

http://jsfiddle.net/gerst20051/sLge3/

http://jsfiddle.net/gerst20051/sLge3/

#9


0  

Using a data URI is the way to go. However, using an SVG instead of a GIF provides more flexibility. You can quickly change the size. Just run this in a JavaScript console:

使用数据URI是可行的方法。但是,使用SVG而不是GIF可提供更大的灵活性。您可以快速更改大小。只需在JavaScript控制台中运行:

var width = 1;
var height = 1;
'data:image/svg+xml;base64,' +
btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"/>`);

Example output:

输出示例:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz4=

I threw together a quick CodePen utility to create transparent SVGs with arbitrary dimensions. It's pretty basic, so you'll need to modify it if you want to add color or other features to the image.

我将一个快速CodePen实用程序拼凑在一起,以创建具有任意维度的透明SVG。它非常基本,因此如果要为图像添加颜色或其他功能,则需要对其进行修改。

The biggest advantage over a single-pixel image is that it allows aspect ratio to be preserved. This is important for dynamically-sized images, as layout is often performed before the src changes to a real image (if that's the intended purpose). Until the src changes, image will be square, which may be undesirable.

单像素图像的最大优势在于它可以保留纵横比。这对于动态大小的图像很重要,因为布局通常在src更改为真实图像之前执行(如果这是预期目的)。直到src改变,图像将是方形的,这可能是不合需要的。