检查是否使用jQuery加载了图片(没有错误)


224

我将JavaScript与jQuery库配合使用,以操作无序列表中包含的图像缩略图。加载映像后,它会做一件事;发生错误时,它会做其他事情。我正在使用jQuery load()error()方法作为事件。在这些事件之后,我检查图像DOM元素的.complete,以确保在jQuery可以注册事件之前尚未加载图像。

它正常工作,除非在jQuery可以注册事件之前发生错误。我能想到的唯一解决方案是使用img onerror属性在全局某处(或其自身的节点上)存储“标志”,该标志表示失败,因此jQuery在检查.complete时可以检查该“存储/节点”。

有人有更好的解决方案吗?

编辑:加粗要点,并在下面添加了更多详细信息: 我正在检查图像是否完整(也称为已加载),然后在图像上添加加载和错误事件。这样,如果在注册事件之前加载了图像,我仍然会知道。如果在事件之后未加载图像,则事件将在事件发生时对其进行处理。问题是,我可以轻松检查图像是否已经加载,但是我不能确定是否发生错误。


您何时注册jQuery事件?也许一些代码会有所帮助。:)
okw

有很多代码,我上面所说的只是我正在做的一个非常简单的版本。我在DOM加载后调用事件,该方法被称为将事件添加到缩略图中。
威廉

Answers:


250

另一种选择是通过创建内存图像元素并将其属性设置为原始图像的原始属性来触发onload和/或onerror事件。这是我的意思的示例:srcsrc

$("<img/>")
    .on('load', function() { console.log("image loaded correctly"); })
    .on('error', function() { console.log("error loading image"); })
    .attr("src", $(originalImage).attr("src"))
;

希望这可以帮助!


27
似乎工作不如我希望的那样。在Google Chrome浏览器中,当图像已经在缓存中时似乎出现了问题。它不会触发load()方法。:(
威廉

4
哎呀,你是对的。Chrome绝对是最令人讨厌的浏览器。在明亮的地方,我想我可能已经找到了解决方法:将图像源设置为“”,然后再返回到原始源。我将更新我的答案。
哈维

1
你应该把.attr线.load.error线。否则,您可能存在在添加这些回调之前图像可能已加载(或遇到错误)并且不会被调用的风险。
卡伦

19
@Xavi Chrome不是最烦人的浏览器,请尝试为Internet Explorer 7或更低版​​本进行开发。除了在图像加载中添加$ _GET参数外,每次都会加载新图像,就像Gromix建议的那样。
SSH

10
.load().error()方法混乱,现在已经过时,使用.on()和使用load,并error为事件。
Firsh-LetsWP.io 2014年

235

依次检查completenaturalWidth属性。

https://stereochro.me/ideas/detecting-broken-images-js

function IsImageOk(img) {
    // During the onload event, IE correctly identifies any images that
    // weren’t downloaded as not complete. Others should too. Gecko-based
    // browsers act like NS4 in that they report this incorrectly.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth and
    // naturalHeight. These give the true size of the image. If it failed
    // to load, either of these should be zero.
    if (img.naturalWidth === 0) {
        return false;
    }

    // No other way of checking: assume it’s ok.
    return true;
}

1
有趣的是,我早些时候在看那篇文章,但我没有意识到他们在做!由于IE中未定义naturalWidth,因此对IE而言是完整的。现在要检查它。
威廉

3
显然,这仅在第一次可靠运行。如果您随后更改图片的src,则至少safari移动版将继续报告naturalWidth和complete的第一个值。
giorgian

5
返回img.complete && typeof img.naturalWidth!='未定义'&& img.naturalWidth!= 0;
阿德里安·塞利

5
@vsync,您可能希望将其用作一次性检查,如果尚未加载映像,请设置“加载”事件处理程序。无需多次运行此检查来锤打CPU。
Michael Martin-Smucker 2014年

2
对于那些好奇的人来说,这几乎就是下面链接的imagesLoaded库的功能。因此,一次性使用它:github.com/desandro/imagesloaded/blob/master/…–
cincodenada

57

根据对元素的W3C HTML规范的了解img,您应该能够使用completenaturalHeight属性的组合来执行此操作,如下所示:

function imgLoaded(imgElement) {
  return imgElement.complete && imgElement.naturalHeight !== 0;
}

从规范的complete属性:

如果满足以下任一条件,则IDL属性complete必须返回true:

  • 省略src属性。
  • 一旦资源被获取,联网任务源将要排队的最终任务已排队。
  • img元素完全可用。
  • img元素已损坏。

否则,该属性必须返回false。

因此,从本质上讲,complete如果图像已完成加载或加载失败,则返回true。因为我们只需要图像成功加载的情况,所以我们还需要检查nauturalHeight属性:

IDL属性,naturalWidth并且naturalHeight必须返回图像的固有宽度和高度(如果可用),以CSS像素为单位,否则为0。

available定义如下:

img始终处于以下状态之一:

  • 不可用 -用户代理尚未获得任何图像数据。
  • 部分可用 -用户代理已获得一些图像数据。
  • 完全可用 -用户代理已获取所有图像数据,并且至少图像尺寸可用。
  • 损坏 -用户代理已经获得了它可以获取的所有图像数据,但是甚至无法解码图像以获取图像尺寸(例如,图像已损坏或不支持格式,或者无法获取数据) 。

当img元素处于部分可用状态或完全可用状态时,可以说它是可用的。

因此,如果图像“损坏”(无法加载),则它将处于损坏状态,而不是可用状态,因此naturalHeight将为0。

因此,检查imgElement.complete && imgElement.naturalHeight !== 0应告诉我们映像是否已成功加载。

您可以在W3C HTML规范中的img元素MDN上阅读有关此内容的更多信息。


1
不起作用是图片已加载样式为“内容:URL”的样式
deathangel908

1
这在带有SVG图像的Firefox中似乎不起作用,因为浏览器报告的自然高度/宽度为0。相关错误:bugzilla.mozilla.org/show_bug.cgi?
id=1328124

20

我尝试了许多不同的方法,这是唯一为我工作的方法

//check all images on the page
$('img').each(function(){
    var img = new Image();
    img.onload = function() {
        console.log($(this).attr('src') + ' - done!');
    }
    img.src = $(this).attr('src');
});

您还可以添加在所有图像均已加载到DOM中并准备就绪后触发的回调函数。这也适用于动态添加的图像。http://jsfiddle.net/kalmarsh80/nrAPk/


jsfiddle链接已损坏
Alex Karshin 2015年

1
我已经测试了上面有趣的读物,但它们在少数常用浏览器上的缓存/未缓存测试之间失败。这个答案与另一个类似,但是我刚刚实施并测试了这个答案,我可以确认它是否适用:EdgeWin10,IE11Win8.1,Win7IE10,Win7IE9,iOS 10.2 Chrome,iOS 10.2 Safari,mac os 10.12 Chrome,mac os 10.12 Safari,mac os 10.12 Firefox,Google Pixel 7.1,三星S5 Android 4.4。不要忘了也使用addEventListener / removeEventListener:D
danjah

13

使用imagesLoadedjavascript库

可与纯Javascript一起使用,并作为jQuery插件使用。

特征:

  • IE8 +正式支持
  • 执照:麻省理工学院
  • 依赖项:无
  • 重量(最小并压缩):最小7kb(轻!)

资源资源


这对我来说非常有效。函数checkImages(imgs){$(imgs).each(function(){$(imgs).imagesLoaded().progress(function(instance,image){if(image.isLoaded == false){console.log(image .img.src +'找不到。'); image.img.src =“ /templates/img/no-image.jpg”;}});}); }
Rooster242 2014年

1
似乎有很多未解决的问题是主要的错误,而开发人员似乎并没有采取很多措施来解决这些问题。到目前为止,这在生产环境中是完全无法使用的。
vsync

3
@vsync您阅读了一些未解决的问题吗?他几乎对所有这些都做出了回应,而且大多数似乎都是其他人很少遇到的无法再现的极端情况。我从来没有在生产中遇到任何问题。
2014年

1
是的,我自己使用它,有时有时不起作用,所以我使用setTimeout来解决失败的情况
vsync

原因很多,为什么要使用imagesLoaded插件:complete似乎未明确支持该属性:无法找到有关浏览器支持的可靠信息源。complete属性似乎也没有明确的规范:HTML5规范是唯一提及它的规范,并且在撰写本文时仍处于草稿版本。如果使用naturalWidthnaturalHeight仅支持IE9 +,则如果使用它来查找是否已加载图像,则需要一些“聪明”的技巧以使其在旧的浏览器上运行,并且必须检查跨浏览器的行为是否一致
Adrien是

8

检索上的页面图像元素的信息
在Chrome和Firefox的测试工作
工作的jsfiddle(打开你的控制台来查看结果)

$('img').each(function(){ // selecting all image element on the page

    var img = new Image($(this)); // creating image element

    img.onload = function() { // trigger if the image was loaded
        console.log($(this).attr('src') + ' - done!');
    }

    img.onerror = function() { // trigger if the image wasn't loaded
        console.log($(this).attr('src') + ' - error!');
    }

    img.onAbort = function() { // trigger if the image load was abort
        console.log($(this).attr('src') + ' - abort!');
    }

    img.src = $(this).attr('src'); // pass src to image object

    // log image attributes
    console.log(img.src);
    console.log(img.width);
    console.log(img.height);
    console.log(img.complete);

});

注意:我使用jQuery,我认为这可以在完整的javascript上实现

我在这里找到了很好的信息OpenClassRoom- >这是一个法语论坛


3

实时网络检测器-在不刷新页面的情况下检查网络状态:( 它不是jquery,但已经过测试,并且100%有效:(在Firefox v25.0上测试)

码:

<script>
 function ImgLoad(myobj){
   var randomNum = Math.round(Math.random() * 10000);
   var oImg=new Image;
   oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
   oImg.onload=function(){alert('Image succesfully loaded!')}
   oImg.onerror=function(){alert('No network connection or image is not available.')}
}
window.onload=ImgLoad();
</script>

<button id="reloadbtn" onclick="ImgLoad();">Again!</button>

如果连接断开,只需按“再次”按钮。

更新1: 自动检测而不刷新页面:

<script>
     function ImgLoad(myobj){
       var randomNum = Math.round(Math.random() * 10000);
       var oImg=new Image;
       oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
       oImg.onload=function(){networkstatus_div.innerHTML="";}
       oImg.onerror=function(){networkstatus_div.innerHTML="Service is not available. Please check your Internet connection!";}
}

networkchecker = window.setInterval(function(){window.onload=ImgLoad()},1000);
</script>

<div id="networkstatus_div"></div>

100%!如果您的图像链接被代理/防火墙阻止或图像服务器没有响应怎么办?您仍然可以使用网络:)
Sen Jacob

这将再次从服务器加载每个图像,从而有意破坏缓存。因此,仅为了检查,您(至少)将所有图像的带宽加倍。此外,它仅检查服务器上是否存在映像,而不检查映像是否已加载到特定位置。也没有办法知道何时加载每个图像。
MariusBalčytis15年

3

在阅读了本页上有趣的解决方案之后,我创建了一个易于使用的解决方案,该解决方案深受SLaks和Noyo的帖子的影响,该帖子似乎正在使用Chrome,IE,Firefox,Safari和Opera(所有在Windows上)。另外,它还可以在我使用的iPhone / iPad模拟器上运行。

该解决方案与SLaks和Noyo的文章之间的主要区别在于,该解决方案主要检查naturalWidth和naturalHeight属性。我发现在当前的浏览器版本中,这两个属性似乎提供了最有用和一致的结果。

当图像已完全且成功加载后,此代码将返回TRUE。当图像尚未完全加载或加载失败时,它将返回FALSE。

您需要注意的一件事是,如果图像是0x0像素的图像,此函数还将返回FALSE。但是这些图像很少见,我想不出一个非常有用的情况,您需要检查一下是否已经加载了0x0像素的图像:)

首先,我们将一个名为“ isLoaded”的新函数附加到HTMLImageElement原型,以便该函数可以在任何图像元素上使用。

HTMLImageElement.prototype.isLoaded = function() {

    // See if "naturalWidth" and "naturalHeight" properties are available.
    if (typeof this.naturalWidth == 'number' && typeof this.naturalHeight == 'number')
        return !(this.naturalWidth == 0 && this.naturalHeight == 0);

    // See if "complete" property is available.
    else if (typeof this.complete == 'boolean')
        return this.complete;

    // Fallback behavior: return TRUE.
    else
        return true;

};

然后,每当需要检查图像的加载状态时,只需调用“ isLoaded”函数即可。

if (someImgElement.isLoaded()) {
    // YAY! The image loaded
}
else {
    // Image has not loaded yet
}

根据giorgian对SLaks和Noyo的帖子的评论,如果您打算更改SRC属性,则该解决方案可能只能用作Safari Mobile的一次性检查。但是,您可以通过使用新的SRC属性创建图像元素而不是在现有图像元素上更改SRC属性来解决此问题。


2

这就是我使用上述方法的组合使其跨浏览器工作的方式(我还需要将图像动态插入dom中):

$('#domTarget').html('<img src="" />');

var url = '/some/image/path.png';

$('#domTarget img').load(function(){}).attr('src', url).error(function() {
    if ( isIE ) {
       var thisImg = this;
       setTimeout(function() {
          if ( ! thisImg.complete ) {
             $(thisImg).attr('src', '/web/css/img/picture-broken-url.png');
          }
       },250);
    } else {
       $(this).attr('src', '/web/css/img/picture-broken-url.png');
    }
});

注意:您将需要为isIE变量提供有效的布尔状态。


2
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

//或作为插件

    $.fn.extend({
      isLoaded: function(){
        return this.prop("complete") && this.prop("naturalWidth") !== 0;
      }
    })

// $(".myImage").isLoaded() 

1

据我了解,.complete属性是非标准的。它可能不是通用的...我注意到它在Firefox和IE中的工作方式似乎有所不同。我正在用javascript加载许多图像,然后检查是否完成。在Firefox中,这似乎很棒。在IE中,这不是因为图像似乎正在另一线程上加载。仅当我在对image.src的赋值与检查image.complete属性之间存在延迟时,此方法才有效。

使用image.onload和image.onerror也不适合我,因为我需要传递一个参数来知道调用函数时我在谈论哪个图像。这样做的任何方法似乎都失败了,因为它实际上似乎传递了相同的功能,而不是传递相同功能的不同实例。因此,我传递给它的用于标识图像的值总是最终成为循环中的最后一个值。我想不出任何办法解决这个问题。

在Safari和Chrome上,即使错误控制台显示了该图像的404,我也看到了image.complete true和naturalWidth的设置,并且我有意删除了该图像以进行测试。但是以上对于Firefox和IE都适用。


嗯,这很有趣。介意发布代码示例,以便尝试一些操作吗?
哈维

1

此代码段帮助我解决了浏览器缓存问题:

$("#my_image").on('load', function() {

    console.log("image loaded correctly"); 
}).each(function() {

     if($(this).prop('complete')) $(this).load();
});

禁用浏览器缓存时,仅以下代码不起作用:

$("#my_image").on('load', function() {
     console.log("image loaded correctly"); 
})

要使其工作,您必须添加:

.each(function() {
     if($(this).prop('complete')) $(this).load();
});

0

使用此JavaScript代码,您可以检查图像是否成功加载。

document.onready = function(e) {
        var imageobj = new Image();
        imageobj.src = document.getElementById('img-id').src;
        if(!imageobj.complete){ 
            alert(imageobj.src+"  -  Not Found");
        }
}

试试这个


0

图像和EventListener的完整加载有很多问题。

无论我如何尝试,结果都不可靠。

但是后来我找到了解决方案。从技术上讲,它不是一个很好的选择,但是现在我从未出现过图像加载失败的情况。

我做了什么:

                    document.getElementById(currentImgID).addEventListener("load", loadListener1);
                    document.getElementById(currentImgID).addEventListener("load", loadListener2);

                function loadListener1()
                    {
                    // Load again
                    }

                function loadListener2()
                {
                    var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
                    alert("Image loaded");
                }

无需一次加载图像,而是直接在第一次加载后第二次加载它,并且两者都通过事件处理程序运行。

我所有的头痛都消失了!


顺便说一句:来自stackoverflow的各位帮助我已经超过一百次。为此非常感谢!


0

这个对我来说很好:)

$('.progress-image').each(function(){
    var img = new Image();
    img.onload = function() {
        let imgSrc = $(this).attr('src');
        $('.progress-image').each(function(){
            if($(this).attr('src') == imgSrc){
                console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
            }
        })
    }
    img.src = $(this).attr('src');
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.