jQuery/JavaScript来替换破碎的图像

Dan*_*ord 531 html javascript jquery broken-image

我有一个包含一堆图像的网页.有时图像不可用,因此在客户端的浏览器中显示损坏的图像.

如何使用jQuery获取图像集,将其过滤为损坏的图像然后替换src?


- 我认为使用jQuery更容易做到这一点,但结果却更容易使用纯粹的JavaScript解决方案,即Prestaul提供的解决方案.

Pre*_*aul 733

处理onError图像事件以使用JavaScript重新分配其源:

function imgError(image) {
    image.onerror = "";
    image.src = "/images/noimage.gif";
    return true;
}
Run Code Online (Sandbox Code Playgroud)
<img src="image.png" onerror="imgError(this);"/>
Run Code Online (Sandbox Code Playgroud)

或者没有JavaScript功能:

<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />
Run Code Online (Sandbox Code Playgroud)

以下兼容性表列出了支持错误工具的浏览器:

http://www.quirksmode.org/dom/events/error.html

  • 您可能想在*设置src之前清除错误*.否则,如果noimage.gif也缺失,则可能最终出现"堆栈溢出". (128认同)
  • 我想并希望我们摆脱javascript事件的内联属性...... (45认同)
  • @redsquare,我完全同意,但这是一个独特的案例.内联是唯一可以附加侦听器的地方,绝对确定在附加侦听器之前事件不会触发.如果您在文档末尾执行此操作或等待加载DOM,则可能会错过某些图像上的错误事件.在事件触发后附加错误处理程序没有任何好处. (36认同)
  • redsquare ......当你明智地控制它们时,它们是完全可以理解的,当你希望你的标记能够反映出实际发生的事情时,它们甚至是有用的. (23认同)
  • 好点NickC,关于显示正在发生的事情的标记,当我看到它时我只是畏缩:P (2认同)

tra*_*vis 194

我使用内置error处理程序:

$("img").error(function () {
    $(this).unbind("error").attr("src", "broken.gif");
});
Run Code Online (Sandbox Code Playgroud)

编辑:error()方法在1.8及更高版本中已弃用.相反,你应该使用.on("error"):

$("img").on("error", function () {
    $(this).attr("src", "broken.gif");
});
Run Code Online (Sandbox Code Playgroud)

  • 如果你使用这种技术,你可以使用"一"方法来避免需要解除绑定事件:$('img').one('error',function(){this.src ='broken.gif';}} ; (109认同)
  • 我认为,如果你没有取消绑定,并且broken.gif src引用因任何原因无法加载,那么浏览器中就会发生不好的事情. (15认同)
  • +1但是你必须解开它吗?它可以在动态图像上很好地工作(例如,在悬停时可以改变的图像),如果你不解除它. (7认同)
  • 下面是一个错误在附加事件处理程序之前触发的情况的示例:http://jsfiddle.net/zmpGz/1/如果有一种故障安全的方法来附加此处理程序,我真的很好奇...... (5认同)
  • @travis,你会在什么时候打这个电话?有没有办法使用这种方法,并确保你的处理程序在错误事件触发之前被附加? (4认同)
  • 有时,图像会动态添加到DOM中,因此,在此处使用事件委派模型可能是有意义的. (2认同)

mou*_*uad 115

如果像我这样的人尝试将error事件附加到动态HTML img标记,我想指出,有一个问题:

显然,img错误事件在大多数浏览器中都不会出现泡沫,这与标准所说的相反.

所以,像下面这样的东西将不起作用:

$(document).on('error', 'img', function () { ... })
Run Code Online (Sandbox Code Playgroud)

希望这对其他人有所帮助.我希望我在这个帖子中看到过这个.但是,我没有.所以,我正在添加它


Dev*_*von 56

这是一个独立的解决方案:

$(window).load(function() {
  $('img').each(function() {
    if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 差不多正确...... IE中的正确图像仍将返回(typeof(this.naturalWidth)=="undefined")== true; - 我将if语句更改为(!this.complete ||(!$.browser.msie &&(typeof this.naturalWidth =="undefined"|| this.naturalWidth == 0))) (5认同)
  • 此规则是因为它可以在页面加载后检测到损坏的图像.我需要这个. (3认同)
  • 独立但需要jQuery? (3认同)

Nic*_*ver 33

我相信这就是你所追求的:jQuery.Preload

这是演示中的示例代码,您指定了加载和未找到的图像,并且您已全部设置:

$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});
Run Code Online (Sandbox Code Playgroud)

  • 是的......这与第一行的答案相关联. (17认同)

小智 23

$(window).bind('load', function() {
$('img').each(function() {
    if((typeof this.naturalWidth != "undefined" &&
        this.naturalWidth == 0 ) 
        || this.readyState == 'uninitialized' ) {
        $(this).attr('src', 'missing.jpg');
    }
}); })
Run Code Online (Sandbox Code Playgroud)

资料来源:http://www.developria.com/2009/03/jquery-quickie---broken-images.html


Nat*_*hur 15

虽然OP希望取代SRC,但我确信许多人在讨论这个问题时可能只想隐藏破碎的图像,在这种情况下,这个简单的解决方案对我来说非常有用:

<img src="img.jpg" onerror="this.style.display='none';" />
Run Code Online (Sandbox Code Playgroud)


Ash*_*med 10

这是一种快速而又脏的方法来替换所有损坏的图像,并且无需更改HTML代码;)

codepen示例

    $("img").each(function(){
        var img = $(this);
        var image = new Image();
        image.src = $(img).attr("src");
        var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
        if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
            $(img).unbind("error").attr("src", no_image).css({
                height: $(img).css("height"),
                width: $(img).css("width"),
            });
        }
  });
Run Code Online (Sandbox Code Playgroud)


小智 8

我找不到适合我需要的脚本,所以我做了一个递归函数来检查损坏的图像,并尝试每四秒重新加载一次,直到它们被修复.

我把它限制为10次尝试,好像它没有被加载,然后图像可能不存在于服务器上,并且该函数将进入无限循环.我还在测试.随意调整它:)

var retries = 0;
$.imgReload = function() {
    var loaded = 1;

    $("img").each(function() {
        if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {

            var src = $(this).attr("src");
            var date = new Date();
            $(this).attr("src", src + "?v=" + date.getTime()); //slightly change url to prevent loading from cache
            loaded =0;
        }
    });

    retries +=1;
    if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
                        // are not present on server, the recursion will break the loop
        if (loaded == 0) {
            setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
        }
        // All images have been loaded
        else {
            // alert("images loaded");
        }
    }
    // If error images cannot be loaded  after 10 retries
    else {
        // alert("recursion exceeded");
    }
}

jQuery(document).ready(function() {
    setTimeout('$.imgReload()',5000);
});
Run Code Online (Sandbox Code Playgroud)


Phi*_*asa 8

这是一种糟糕的技术,但它几乎得到了保证:

<img ...  onerror="this.parentNode.removeChild(this);">
Run Code Online (Sandbox Code Playgroud)


Dyl*_*ade 6

这多年来一直让我感到沮丧。我的 CSS 修复在img. 当动态图像src未加载到前台时,占位符在 的img背景上可见。如果您的图像具有默认尺寸(例如heightmin-heightwidth/或min-width),则此方法有效。

您会看到损坏的图像图标,但这是一个改进。测试到IE9成功。iOS Safari 和 Chrome 甚至不显示损坏的图标。

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}
Run Code Online (Sandbox Code Playgroud)

添加一点动画,以便src有时间加载而不会出现背景闪烁。Chrome 在后台平滑淡出,但桌面版 Safari 却不然。

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
  animation: fadein 1s;                     
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}
Run Code Online (Sandbox Code Playgroud)

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}
Run Code Online (Sandbox Code Playgroud)
.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
  animation: fadein 1s;                     
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}
Run Code Online (Sandbox Code Playgroud)


Axe*_*xel 5

这是JavaScript,应该是跨浏览器兼容的,并且没有丑陋的标记onerror="":

var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
    validateImage = function( domImg ) {
        oImg = new Image();
        oImg.onerror = function() {
            domImg.src = sPathToDefaultImg;
        };
        oImg.src = domImg.src;
    },
    aImg = document.getElementsByTagName( 'IMG' ),
    i = aImg.length;

while ( i-- ) {
    validateImage( aImg[i] );
}
Run Code Online (Sandbox Code Playgroud)

CODEPEN:


hor*_*rro 5

如果您插入了imgwith innerHTML,例如:$("div").innerHTML = <img src="wrong-uri">,如果失败,您可以加载另一个图像,例如:

<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>

<img src="wrong-uri" onerror="javascript:imgError(this)">
Run Code Online (Sandbox Code Playgroud)

为什么javascript: _需要?因为通过脚本标签注入 DOM 的脚本在innerHTML注入时不会运行,所以你必须明确。


Bar*_*ode 5

您可以使用GitHub自己的提取:

前端:https://github.com/github/fetch
或Backend,Node.js版本:https://github.com/bitinn/node-fetch

fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }
Run Code Online (Sandbox Code Playgroud)

编辑:这种方法将取代XHR,据说已经在Chrome中.对于将来阅读此内容的任何人,您可能不需要包含上述库.