检测图像何时加载的独立于浏览器的方法

IT技术 javascript dom
2021-02-08 02:45:01

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

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

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

6个回答

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

警告:现在是 2017 年,我仍然时不时地在这方面获得积分,请仅将其用于研究目的。我目前不知道如何检测图像加载状态,但可能有比这更优雅的方法……至少我非常希望有。我强烈建议不要在没有更多研究的情况下在生产环境中使用我的代码。

警告第二部分 Electric Boogaloo:现在是 2019 年,现在大多数 jQuery 功能都内置到 vanilla JS 中。如果您仍在使用它,可能是时候停下来考虑转到MDN并阅读 vanilla JS 必须提供的一些新的和有趣的东西。


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

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


这将在图像附加到正文之前发出警报,因为当图像加载到内存中时会触发 load 事件。它完全按照您的要求执行:使用 test.jpg 的 src 创建一个图像,当 test.jpg 加载时发出警报,然后将其附加到正文。

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

这将提醒,在图像插入正文后,再次执行您告诉它的操作:创建图像,设置事件(未设置 src,因此尚未加载),将图像附加到正文(仍然没有 src),现在设置 src... 现在图像已加载,因此事件被触发。

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

您当然也可以添加错误处理程序并使用 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');

根据@ChrisKempen 的请求...

这是在加载 DOM 后确定图像是否损坏的非事件驱动方式。这段代码是StereoChrome一篇文章的衍生代码,它使用自然宽度、自然高度和完整属性来确定图像是否存在。

$('img').each(function() {
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) {
        alert('broken image');
    }
});
@paulj 请注意naturalWidth&naturalHeightIE9+ 兼容,请参阅此以获得跨浏览器支持stackoverflow.com/a/7869044/759452jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie,可能受到css- 的启发技巧.com/snippets/jquery/get-an-images-native-width
2021-03-26 02:45:01
警告:来自 jquery 文档:与图像一起使用时加载事件的注意事项:开发人员尝试使用 .load() 快捷方式解决的一个常见挑战是在图像(或图像集合)完全加载时执行函数。有几个已知的警告应该注意。它们是: 它不能始终如一地跨浏览器工作,也不能可靠地跨浏览器 如果图像 src 设置为与以前相同的 src 它不能在 WebKit 中正确触发 它不能正确地使 DOM 树冒泡 可以停止为图像触发已经存在于浏览器缓存中的
2021-03-30 02:45:01
@ChrisKempen——我在上面的帖子中为你添加了一个非事件驱动的方法,也请查看我的代码派生自的原始文章。
2021-03-31 02:45:01
我参加派对的时间更晚,但是如果图像已经添加并且您需要检查它们是否已加载怎么办?感谢您的任何想法/建议!:)
2021-04-02 02:45:01
@paulj - 谢谢!非常有趣的解决方案!+1
2021-04-08 02:45:01

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

可能与本次讨论有关的内容,尽管不一定是您需要的答案,是本次讨论:

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


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

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

这可能是真的,但图像的加载是事实上的标准(自 Netscape Navigator 4 以来一直可用)
2021-03-15 02:45:01
@Christoph - 在你的近视中,你忘记了两件事:1)我表示它可能与“讨论无关”,但更重要的是,2)其他人有一天可能会登陆这个页面,因为他们遇到了我的问题链接到并来到这里是因为他们正在为他们的特定问题搜索 SO。如果我在 erlang 中发布了一个关于元组问题的链接,我会看到你很生气,但我觉得我的评论是相关的。
2021-03-21 02:45:01
@Jason:我并不难过或任何事情,但是您的回答 imo 表明将 onload 与图像一起使用比实际情况更成问题;在讨论 vanilla JS 时链接到特定于 GWT 的问题对我来说似乎有点奇怪 - 这不是错误,而是合理且记录在案的行为 - 检查msdn.microsoft.com/en-us/library/cc197055(VS .85).aspx
2021-03-30 02:45:01
您提到的 Image.onload 问题是特定于 GWT 的 - 请参阅code.google.com/p/google-web-toolkit/issues/detail?id=863#c5Image.onload 必须在 Image.src 之前设置以避免这种情况,这已经被 Josh 暗中提到了
2021-04-03 02:45:01
当然,我从来没有说过这不是他可以指望的,只是确保他知道规范 - 忽略规范后果自负。
2021-04-06 02:45:01

我发现的唯一可靠的方法是像这样在客户端完成所有操作......

var img = new Image();
img.onload = function() {
  alert('Done!');
}
img.src = '/images/myImage.jpg';
尽管少数浏览器支持它,但 W3C 标准不支持“onload”事件,因此并非所有浏览器都需要或必须支持它。
2021-04-08 02:45:01

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

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

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

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

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

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

再说一次,我知道这一点,但是如果没有其他原因要准确理解您指出的内容,那么注意规范的内容总是很好的 - 它们与现实脱节并且需要更新。顺便说一下,什么是“js-hacks”,为什么需要它?我从您的个人资料中注意到您创建了它,但很难发现它是什么,因为您的网站缺乏信息,而且我没有时间通读所有文件来寻找这些信息。
2021-03-22 02:45:01
尽管少数浏览器支持它,但 W3C 标准不支持“onload”事件,因此并非所有浏览器都需要或必须支持它。
2021-03-29 02:45:01
@Jason:js-hacks 是一个转储独立脚本的地方,这样我就可以链接到最新版本;它们中的大多数基本上是无用的或只是为了好玩,但是当您不想使用成熟的框架时,也有一些非常好用;问题是,我懒得写文档,即使有些脚本可能值得向更广泛的公众展示(例如mercurial.intuxication.org/hg/js-hacks/raw-file/tip/capture.js非常好并改变了我的事件处理方法......)
2021-03-29 02:45:01
@Christoph:啊,好吧 - 我不确定,并认为这可能是某种框架。我是 MochiKit 的忠实用户(现在已经大量使用它 3 年了)并且在过去 3 个月开始使用 jQuery,但我喜欢 JavaScript 并且喜欢学习关于它的新事物,也许我会从你的脚本中收集一些有用的东西。谢谢。
2021-04-03 02:45:01
好吧,当“一些浏览器”似乎是 NN4 中的每个主流浏览器时,可以合理地假设该功能不会很快消失。尽管很遗憾,W3C 规范很少反映 Web 开发人员面临的现实......
2021-04-07 02:45:01

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

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