jQuery / JavaScript来替换破碎的图像

时间:2008-09-18 13:53:33

标签: javascript jquery html brokenimage

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

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


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

31 个答案:

答案 0 :(得分:710)

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

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

或没有JavaScript函数:

<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />

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

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

答案 1 :(得分:190)

我使用内置的error处理程序:

$("img").error(function () {
  $(this).unbind("error").attr("src", "broken.gif");
});

修改 error()方法已在1.8及更高版本中弃用。相反,您应该使用.on("error")代替:

$("img").one("error", function () {
  $(this).attr("src", "broken.gif");
});

答案 2 :(得分:114)

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

在大多数浏览器中,显然有img个错误事件 don't bubble ,与standard所说的相反。

因此,以下内容无效

$(document).on('error', 'img', function () { ... })

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

答案 3 :(得分:55)

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

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

答案 4 :(得分:32)

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

以下是演示中的示例代码,您指定了加载和未找到的图像,并且您已完成设置:

$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});

答案 5 :(得分:23)

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

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

答案 6 :(得分:10)

虽然OP希望取代SRC,但我确信很多人在打这个问题时可能只想隐藏破碎的图像,在这种情况下this simple solution对我来说很有用:

<img src="someimage.jpg" onerror="this.style.display='none';" />

答案 7 :(得分:10)

以下是替换所有损坏图像的快捷方式,无需更改HTML代码;)

codepen example

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

答案 8 :(得分: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);
});

答案 9 :(得分:8)

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

<img ...  onerror="this.parentNode.removeChild(this);">

答案 10 :(得分: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;
    }
  }

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

答案 11 :(得分: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] );
}

CODEPEN:

答案 12 :(得分:4)

以下是使用JQuery包装的HTML5 Image对象的示例。调用主映像URL的加载函数,如果该加载导致错误,请用备份URL替换映像的src属性。

function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
    var $img = $('#' + imgId);
    $(new Image()).load().error(function() {
        $img.attr('src', backupUrl);
    }).attr('src', primaryUrl)
}

<img id="myImage" src="primary-image-url"/>
<script>
    loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>

答案 13 :(得分:4)

纯JS。 我的任务是:如果图像&#39; bl-once.png&#39;是空的 - &gt;从数组列表中插入第一个(没有#404状态)图像(在当前目录中):

&#13;
&#13;
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
&#13;
&#13;
&#13;

也许需要改进,但是:

&#13;
&#13;
var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array
    var path;
    var imgNotFounded = true; // to mark when success

    var replaceEmptyImage = {
        insertImg: function (elem) {

            if (srcToInsertArr.length == 0) { // if there are no more src to try return
                return "no-image.png";
            }
            if(!/undefined/.test(elem.src)) { // remember path
                path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"
            }
            var url = path + "/" + srcToInsertArr[0];

            srcToInsertArr.splice(0, 1); // tried 1 src

            
                if(imgNotFounded){ // while not success
                    replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE
                }
            

        },
        getImg: function (src, path, elem) { // GET IMAGE

            if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"
                
                var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]
                var name = pathArr[pathArr.length - 1]; // "needed.png"

                xhr = new XMLHttpRequest();
                xhr.open('GET', src, true);
                xhr.send();

                xhr.onreadystatechange = function () {

                    if (xhr.status == 200) {
                        elem.src = src; // insert correct src
                        imgNotFounded = false; // mark success
                    }
                    else {
                        console.log(name + " doesn't exist!");
                        elem.onerror();
                    }

                }
            }
        }

    };
&#13;
&#13;
&#13;

因此,它会插入正确的&#39; needed.png&#39;到我的src或&#39; no-image.png&#39;来自目前的目录。

答案 14 :(得分:4)

我使用“onerror”事件创建了一个fiddle来替换损坏的图像。 这可能对你有所帮助。

    //the placeholder image url
    var defaultUrl = "url('https://sadasd/image02.png')";

    $('div').each(function(index, item) {
      var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '$1');
      $('<img>', {
        src: currentUrl
      }).on("error", function(e) {
        $this = $(this);
        $this.css({
          "background-image": defaultUrl
        })
        e.target.remove()
      }.bind(this))
    })

答案 15 :(得分:4)

我在查看this other SO post时发现了这篇文章。以下是我在那里给出的答案的副本。

我知道这是一个老线程,但React已经变得流行,或许,使用React的人会来这里寻找同样问题的答案。

所以,如果您使用的是React,您可以执行以下操作,这是React团队的Ben Alpert提供的答案原件here

getInitialState: function(event) {
    return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
    this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
    return (
        <img onError={this.handleError} src={src} />;
    );
}

答案 16 :(得分:4)

通过使用Prestaul's answer,我添加了一些检查,我更喜欢使用jQuery方式。

<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>

function imgError(image, type) {
    if (typeof jQuery !== 'undefined') {
       var imgWidth=$(image).attr("width");
       var imgHeight=$(image).attr("height");

        // Type 1 puts a placeholder image
        // Type 2 hides img tag
        if (type == 1) {
            if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
                $(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
            } else {
               $(image).attr("src", "http://lorempixel.com/200/200/");
            }
        } else if (type == 2) {
            $(image).hide();
        }
    }
    return true;
}

答案 17 :(得分:4)

如果您已将imginnerHTML一起插入,例如:$("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)">

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

答案 18 :(得分:4)

CoffeeScript变体:

我修复了Turbolinks的一个问题,导致.error()方法有时会在Firefox中引发,即使图像真的存在。

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)

答案 19 :(得分:4)

使用

更好地打电话
jQuery(window).load(function(){
    $.imgReload();
});

因为使用document.ready并不一定意味着加载图像,只加载HTML。因此,不需要延迟呼叫。

答案 20 :(得分:3)

我用这两个简单的函数解决了我的问题:

function imgExists(imgPath) {
    var http = jQuery.ajax({
                   type:"HEAD",
                   url: imgPath,
                   async: false
               });
    return http.status != 404;
}

function handleImageError() {
    var imgPath;

    $('img').each(function() {
        imgPath = $(this).attr('src');
        if (!imgExists(imgPath)) {
            $(this).attr('src', 'images/noimage.jpg');
        }
    });
}

答案 21 :(得分:3)

我不确定是否有更好的方法,但我可以想到一个hack来获取它 - 你可以将Ajax发布到img URL,并解析响应以查看图像是否实际返回。如果它以404或者其他形式返回,那么换掉img。虽然我预计这会很慢。

答案 22 :(得分:3)

jQuery 1.8

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .error(function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

jQuery 3

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .on("error", function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

reference

答案 23 :(得分:2)

这让我多年来一直很沮丧。我的CSS修复程序在img上设置了背景图像。当动态图片src未加载到前景时,img的bg上会显示占位符。如果您的图片具有默认尺寸(例如heightmin-heightwidth和/或min-width),则此方法有效。

你会看到破碎的图像图标,但这是一个改进。成功测试了IE9。 iOS Safari和Chrome甚至没有显示破损的图标。

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

添加一点动画,以便在没有背景闪烁的情况下加载src时间。 Chrome在后台平滑淡出,但桌面Safari却没有。

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

@-webkit-keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

答案 24 :(得分:2)

;(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
    return this.one('error', function () {
        var self = this;
        this.src = (fallback || 'http://lorempixel.com/$width/$height')
        .replace(/\$(\w+)/g, function (m, t) { return self[t] || ''; });
    });
};

您可以通过$*传递占位符路径并从失败的图像对象中访问其中的所有属性:

$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');

http://jsfiddle.net/ARTsinn/Cu4Zn/

答案 25 :(得分:2)

如果无法加载图像(例如,因为它不在提供的URL中),图像URL将更改为默认值,

有关.error()

的更多信息

&#13;
&#13;
$('img').on('error', function (e) {
  $(this).attr('src', 'broken.png');
});
&#13;
&#13;
&#13;

答案 26 :(得分:2)

即使备份图片无法加载,我认为我在window的{​​{1}}上有更优雅的事件委派和事件捕获方式。

error
img {
  width: 100px;
  height: 100px;
}

重点是:

  1. 将代码放在<script> window.addEventListener('error', windowErrorCb, { capture: true }, true) function windowErrorCb(event) { let target = event.target let isImg = target.tagName.toLowerCase() === 'img' if (isImg) { imgErrorCb() return } function imgErrorCb() { let isImgErrorHandled = target.hasAttribute('data-src-error') if (!isImgErrorHandled) { target.setAttribute('data-src-error', 'handled') target.src = 'backup.png' } else { //anything you want to do console.log(target.alt, 'both origin and backup image fail to load!'); } } } </script> <img id="img" src="error1.png" alt="error1"> <img id="img" src="error2.png" alt="error2"> <img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">中并作为第一个内联脚本执行。因此,它会监听脚本之后发生的错误。

  2. 使用事件捕获来捕获错误,尤其是对于那些没有冒泡的事件。

  3. 使用事件委托,避免在每个图像上绑定事件。

  4. 在给出head之后给错误img元素一个属性,以避免backup.png及后续无限循环消失,如下所示:

  5. img error-&gt; backup.png-&gt; error-&gt; backup.png-&gt;错误 - &gt; ,,,,,

答案 27 :(得分:1)

我遇到了同样的问题。这段代码适合我的情况。

// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});

答案 28 :(得分:1)

有时使用Followers {#329 ▼ #attributes: array:4 [▼ "id" => 22 "user_id" => 1 "follower_id" => 1 "type" => 0 ] 事件是不可行的,例如因为您正在尝试在已加载的页面上执行某些操作,例如当您通过控制台运行代码,书签或异步加载的脚本时。在这种情况下,检查errorimg.naturalWidth是否为0似乎可以解决问题。

例如,这是一个从控制台重新加载所有损坏图像的片段:

img.naturalHeight

答案 29 :(得分:1)

我使用延迟加载,必须执行此操作才能使其正常工作:

lazyload();

var errorURL = "https://example.com/thisimageexist.png";

$(document).ready(function () {
  $('[data-src]').on("error", function () {
    $(this).attr('src', errorURL);
  });
});

答案 30 :(得分:0)

我发现这是最好的方法,如果任何图像第一次加载失败,都会将其从DOM中完全删除。执行console.clear()可使控制台窗口保持干净,因为使用try / catch块不能忽略404错误。

$('img').one('error', function(err) {
    // console.log(JSON.stringify(err, null, 4))
    $(this).remove()
    console.clear()
})