jQuery/JavaScript to replace broken images
我有一个网页,上面有一堆图片。有时图像不可用,因此客户机的浏览器中会显示损坏的图像。
如何使用jquery获取图像集,将其过滤为断开的图像,然后替换SRC?
--我原以为用jquery做这件事会更容易些,但事实证明,仅仅使用纯JavaScript解决方案(即Prestaul提供的解决方案)就容易多了。
处理图像的
1 2 3 4 5 | function imgError(image) { image.onerror =""; image.src ="/images/noimage.gif"; return true; } |
1 | <img src="image.png" onerror="imgError(this);"/> |
号
或者没有javascript函数:
1 | <img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" /> |
下表列出了支持错误功能的浏览器:
http://www.quirksmode.org/dom/events/error.html
我使用内置的
1 2 3 | $("img").error(function () { $(this).unbind("error").attr("src","broken.gif"); }); |
。
编辑:1.8及更高版本中不推荐使用
1 2 3 | $("img").one("error", function () { $(this).attr("src","broken.gif"); }); |
。
如果像我这样的人试图将
显然,在大多数浏览器中,
因此,像下面这样的事情是行不通的:
1 | $(document).on('error', 'img', function () { ... }) |
。
希望这对其他人有帮助。我真希望我能在这条线上看到这个。但是,我没有。所以,我要补充一下
这里有一个独立的解决方案:
1 2 3 4 5 6 7 8 | $(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'; } }); }); |
我相信这就是你想要的:jquery.preload
下面是演示中的示例代码,您指定了加载和未找到的图像,并且已经设置好了:
1 2 3 4 | $('#images img').preload({ placeholder:'placeholder.jpg', notFound:'notfound.jpg' }); |
。
1 2 3 4 5 6 7 8 | $(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.developeria.com/2009/03/jquery-quickie---break-images.html
虽然OP希望替换SRC,但我相信很多人在回答这个问题时,可能只希望隐藏损坏的图像,在这种情况下,这个简单的解决方案对我很有用:
1 | <img src="someimage.jpg" onerror="this.style.display='none';" /> |
。
这里有一个快速而肮脏的方法来替换所有损坏的图像,并且不需要更改HTML代码;)
代码笔示例
1 2 3 4 5 6 7 8 9 10 11 12 | $("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"), }); } }); |
号
这是一种糟糕的技术,但它几乎可以保证:
1 | <img ... onerror="this.parentNode.removeChild(this);"> |
号
我找不到适合我需要的脚本,所以我做了一个递归函数来检查损坏的图像,并尝试每四秒钟重新加载一次,直到它们被修复。
我将它限制为10次尝试,就好像它没有被加载一样,那么服务器上的映像可能不存在,函数将进入一个无限循环。不过,我仍在测试。请随意调整:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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); }); |
。
您可以使用Github自己的fetch:
前端:https://github.com/github/fetch或者对于后端,使用node.js版本:https://github.com/bitin/node-fetch
1 2 3 4 5 6 7 8 | fetch(url) .then(function(res) { if (res.status == '200') { return image; } else { return placeholder; } } |
编辑:这个方法将取代XHR,而且应该已经在Chrome中了。对于将来阅读此内容的任何人,您可能不需要包含上述库。
这是Javascript,应该是跨浏览器兼容的,并且没有难看的标记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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] ); } |
代码笔:
更好的呼叫使用
1 2 3 | jQuery(window).load(function(){ $.imgReload(); }); |
因为使用
咖啡描述变体:
我之所以这么做是为了修复turbolinks的一个问题,它有时会导致firefox中出现.error()方法,即使图像确实存在。
1 2 3 | $("img").error -> e = $(@).get 0 $(@).hide() if !$.browser.msie && (typeof this.naturalWidth =="undefined" || this.naturalWidth == 0) |
号
通过使用Prestaul的答案,我添加了一些检查,我更喜欢使用jquery方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <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; } |
号
如果您已将您的
1 2 3 4 5 6 7 | function imgError(img) { img.error=""; img.src="valid-uri"; } <img src="wrong-uri" onerror="javascript:imgError(this)"> |
。
为什么需要
我在看另一个这样的帖子时发现了这个帖子。下面是我在那里给出的答案的副本。
我知道这是一条古老的线索,但是react已经很流行了,也许,使用react的人会来这里寻找相同问题的答案。
因此,如果您使用react,您可以执行如下操作,这是react团队的Ben Alpert提供的原始答案
1 2 3 4 5 6 7 8 9 10 11 | 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} />; ); } |
号
我创建了一个小提琴,用"onerror"事件替换损坏的图像。这可能对你有帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //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)) }) |
下面是一个使用jquery包装的html5图像对象的示例。调用主图像URL的加载函数,如果该加载导致错误,请用备份URL替换图像的src属性。
1 2 3 4 5 6 7 8 9 10 | 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"/> loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url'); |
纯JS。我的任务是:如果图像"bl once.png"为空,则从数组列表(在当前目录中)插入第一个(状态不是404)图像:
1 | <img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)"> |
。
也许需要改进,但是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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(); } } } } }; |
。
所以,它会将正确的'needed.png'插入到我的SRC中,或者从当前目录中插入'no image.png'。
我用这两个简单的函数解决了我的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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'); } }); } |
号
查询1.8
1 2 3 4 5 6 | // If missing.png is missing, it is replaced by replacement.png $("img" ) .error(function() { $( this ).attr("src","replacement.png" ); }) .attr("src","missing.png" ); |
查询3
1 2 3 4 5 6 | // If missing.png is missing, it is replaced by replacement.png $("img" ) .on("error", function() { $( this ).attr("src","replacement.png" ); }) .attr("src","missing.png" ); |
。
参考
我不确定是否有更好的方法,但我可以想到一个黑客来获得它-你可以Ajax发布到img的URL,并解析响应以查看图像是否真的回来了。如果它以404或其他形式返回,那么换掉IMG。尽管我预计这会很慢。
1 2 3 4 5 6 7 | ;(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] || ''; }); }); }; |
号
您可以通过
1 | $('img').fallback('http://dummyimage.com/$widthx$height&text=$src'); |
号
http://jsfiddle.net/artsinn/cu4zn/
如果无法加载图像(例如,因为它不在提供的URL中),则图像URL将更改为默认值,
有关.error()的详细信息
1 2 3 | $('img').on('error', function (e) { $(this).attr('src', 'broken.png'); }); |
号
我认为,即使在备份映像加载失败的情况下,在
1 2 3 4 | img { width: 100px; height: 100px; } |
号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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!'); } } } <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"> |
号
重点是:
将代码放入
使用事件捕获来捕获错误,尤其是对于那些不冒泡的事件。
使用避免在每个映像上绑定事件的事件委托。
在给错误的
img error->backup.png->error->backup.png->error->
多年来这一直让我很沮丧。我的CSS修复程序在
你会看到破碎的图像图标,但这是一个改进。成功测试到IE9。iOS Safari和Chrome甚至没有显示损坏的图标。
1 2 3 4 | .dynamicContainer img { background: url('/images/placeholder.png'); background-size: contain; } |
号
添加一点动画,让
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | .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; } } |
号
我也有同样的问题。这个代码在我的案例中很有效。
1 2 3 4 5 6 | // Replace broken images by a default img $('img').each(function(){ if($(this).attr('src') === ''){ this.src = '/default_feature_image.png'; } }); |
有时使用
例如,下面是从控制台重新加载所有损坏图像的片段:
1 2 3 4 5 | $$("img").forEach(img => { if (!img.naturalWidth && !img.naturalHeight) { img.src = img.src; } } |
。
我发现这是最有效的,如果第一次加载任何图像失败,它将完全从DOM中删除。执行
1 2 3 4 5 | $('img').one('error', function(err) { // console.log(JSON.stringify(err, null, 4)) $(this).remove() console.clear() }) |
号