it-swarm-tr.com

Kırık görüntüleri değiştirmek için jQuery / JavaScript

Bir sürü resim içeren bir web sayfam var. Bazen görüntü kullanılamayabilir, bu nedenle müşterinin tarayıcısında bozuk bir görüntü görüntülenir.

Görüntü kümesini elde etmek, kırık görüntülere filtre uygulamak ve sonra src'yi değiştirmek için jQuery'i nasıl kullanırım?


- Bunu jQuery ile yapmanın daha kolay olacağını düşündüm, ancak sadece Prestaul tarafından sağlanan saf bir JavaScript çözümü kullanmak daha kolay oldu.

516
Dan Lord

JavaScript ile kaynağını yeniden atamak için görüntünün onError olayını işleyin:

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

Veya bir JavaScript işlevi olmadan:

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

Aşağıdaki uyumluluk tablosu, hata özelliğini destekleyen tarayıcıları listeler:

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

714
Prestaul

Dahili error işleyicisini kullanıyorum:

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

Düzenleme: error() yöntemi 1.8 ve daha yüksek sürümlerde kullanımdan kaldırılmıştır. Bunun yerine, .on("error") işlevini kullanmalısınız:

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

Benim gibi biri, error olayını dinamik bir HTML img etiketine eklemeye çalışırsa, şunu belirtmek isterim ki bir yakalama var:

Görünüşe göre img hata olayları kabarcık yapma çoğu tarayıcıda, standart ne söylediğinin aksine .

Dolayısıyla, aşağıdaki gibi bir şey çalışmaz :

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

Umarım bu başkasına yardımcı olacaktır. Keşke bunu bu başlıkta görseydim. Fakat yapmadım. Yani ekliyorum

114
mouad

İşte bağımsız bir çözüm:

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

Neyin peşinde olduğuna inanıyorum: jQuery.Preload

Demodan örnek kod aşağıdadır, yükleme ve resimleri bulamıyorsunuz ve hepsini ayarladınız:

$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});
32
Nick Craver
$(window).bind('load', function() {
$('img').each(function() {
    if((typeof this.naturalWidth != "undefined" &&
        this.naturalWidth == 0 ) 
        || this.readyState == 'uninitialized' ) {
        $(this).attr('src', 'missing.jpg');
    }
}); })

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

23
Mohamad

İşte tüm bozuk görüntüleri değiştirmek için hızlı ve kirli bir yoldur ve HTML kodunu değiştirmenize gerek yoktur;)

codepen örneği

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

OP, SRC'nin yerini almaya çalışırken, bu soruyu vuran birçok insanın yalnızca bozuk görüntüyü gizlemek isteyebileceğinden eminim, bu durumda bu basit çözüm benim için harika çalıştı:

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

İhtiyaçlarıma uygun bir senaryo bulamadım, bu yüzden kırık görüntüleri kontrol etmek ve düzeltilinceye kadar her dört saniyede bir yeniden yüklemeye çalışmak için özyinelemeli bir işlev yaptım.

10 denemeyle sınırlandırılmışım, sanki resim sunucuda bulunmuyor ve işlev sonsuz bir döngüye giriyormuş gibi. Hala test ediyorum. Tweak çekinmeyin :)

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);
});
8
Shade

Bu berbat bir teknik, ama neredeyse garantili:

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

Bu JavaScript, çapraz tarayıcı uyumlu olmalı ve çirkin biçimlendirme olmadan teslim eder 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:

5
Axel

Bunun için GitHub’ın kendi alımını kullanabilirsiniz:

Ön uç: https://github.com/github/fetch
veya Backend için bir Node.js sürümü: https://github.com/bitinn/node-fetch

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

Düzenleme: Bu yöntem, XHR'nin yerini alacak ve sözde Chrome'da zaten var. Gelecekte bunu okuyan kimseye, yukarıda belirtilen kütüphaneye ihtiyaç duymayabilirsiniz.

5
BarryMode

img'nizi innerHTML ile eklediyseniz, şöyle: $("div").innerHTML = <img src="wrong-uri">, eğer başarısız olursa başka bir görüntüyü yükleyebilirsiniz, örneğin:

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

<img src="wrong-uri" onerror="javascript:imgError(this)">

Neden javascript: _need gerekiyor? DOM'a innerHTML komut dosyası etiketleri aracılığıyla enjekte edilen komut dosyaları enjekte edildikleri sırada çalıştırılmadığından, açık olması gerekir.

4
horro

JQuery tarafından sarılmış HTML5 Image nesnesini kullanan bir örnek. Birincil görüntü URL'si için load işlevini çağırın ve bu yük bir hataya neden olursa, görüntünün src niteliğini bir yedek URL ile değiştirin.

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>
4
Kurt Hartmann

"Onerror" olayını kullanarak kırık görüntünün yerini almak için bir keman oluşturdum. Bu size yardımcı olabilir.

    //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))
    })
4
Ninjaneer

Prestaul's answer komutunu kullanarak bazı kontroller ekledim ve jQuery yöntemini kullanmayı tercih ediyorum.

<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;
}
4
trante

Kullanarak daha iyi çağrı

jQuery(window).load(function(){
    $.imgReload();
});

document.ready kullanmak, görüntülerin yüklendiğini, yalnızca HTML'yi gerektirmez. Dolayısıyla, gecikmeli bir aramaya gerek yoktur.

4
Shade

CoffeeScript değişken:

Turbolinks ile .error () yönteminin Firefox'ta bazen görüntü gerçekten var olsa bile ortaya çıkmasına neden olan bir sorunu gidermek için yaptım.

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

Saf JS. Görevim şuydu: 'bl-once.png' görüntüsü boşsa -> dizi listesinden (şu anki dizine) ilk (404 durumu olmayan) resmi ekleyin:

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

Belki de iyileştirilmesi gerekiyor, ama:

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

                }
            }
        }

    };

Bu yüzden src'ye doğru 'needed.png' ya da geçerli dir'den 'no-image.png' yazacağım.

Bu yazıyı bu diğer SO yayına bakarken buldum. Aşağıda orada verdiğim cevabın bir kopyası var.

Bunun eski bir konu olduğunu biliyorum ama React popüler hale geldi ve belki de React'i kullanan biri buraya gelecek ve aynı soruyu cevaplayacak.

Yani, React'i kullanıyorsanız, aşağıdaki gibi bir şey yapabilirsiniz; bu, React of React ekibinden Ben Alpert tarafından sağlanan bir cevap aslıydı burada

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} />;
    );
}
4
Jordan Bonitatis

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" );

referans

3
Nabi K.A.Z.

Sorunumu bu iki basit işlevle çözdüm:

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

Daha iyi bir yol olup olmadığından emin değilim, ancak bunu elde etmek için bir hack düşünebilirim - Ajax'ı img URL'sine gönderebilir ve resmin gerçekten geri gelip gelmediğini görmek için yanıtı çözümleyebilirsiniz. Bir 404 ya da başka bir şey olarak geri döndü, sonra img çıkarın. Yine de bunun oldukça yavaş olmasını bekliyorum.

3
Chii

Bu yıllardır beni sinir ediyor. CSS düzeltmem img 'nin arkaplan görüntüsünü ayarlar. Dinamik bir görüntü src ön plana yüklenmediğinde, img 'in bg dosyasında bir yer tutucu görünür. Bu, resimlerinizin varsayılan bir boyutu varsa çalışır (ör. height, min-height, width ve/veya min-width).

Kırık görüntü simgesini göreceksiniz ancak bu bir gelişme. IE9'a başarıyla test edildi. iOS Safari ve Chrome, bozuk bir simge bile göstermiyor.

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

Arka plan titremesi olmadan yüklenecek src zamanını vermek için küçük bir animasyon ekleyin. Chrome arka planda yumuşak bir şekilde kayboluyor ancak masaüstü Safari'de yok.

.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; }
}
2
Dylan Valade

Yedek resim yüklenemediğinde bile olay heyeti ve window 'ın error üzerinde olay yakalama konusunda daha şık bir yolum olduğunu düşünüyorum.

img {
  width: 100px;
  height: 100px;
}
<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">

Önemli olan :

  1. Kodu head içine yerleştirin ve ilk satır içi komut dosyası olarak çalıştırıldı. Böylece, senaryodan sonra meydana gelen hataları dinleyecektir.

  2. Hataları yakalamak için, özellikle kabarcıklı olmayan olaylar için olay yakalamayı kullanın.

  3. Her görüntüdeki bağlayıcı olayları engelleyen olay temsilcisi kullanın.

  4. backup.png öğesinin ve aşağıdaki gibi sonsuz döngünün kaybolmasını önlemek için backup.png işlevini verdikten sonra img öğesine bir öznitelik verin.

img error-> backup.png-> error-> backup.png-> error -> ,

2
xianshenglu

Resim yüklenemiyorsa (örneğin, verilen URL’de bulunmadığından), resim URL’si varsayılan

Daha fazlası için . Error ()

$('img').on('error', function (e) {
  $(this).attr('src', 'broken.png');
});
2
CasperSL
;(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] || ''; });
    });
};

Bir yer tutucu yolunu geçirebilir ve arızalı görüntü nesnesindeki tüm özelliklere $* yoluyla erişebilirsiniz:

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

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

2
yckart

Bende de aynı problem var. Bu kod benim davamda iyi çalışıyor.

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

Bazen error olayını kullanmak uygun değildir, ör. çünkü önceden yüklenmiş bir sayfada, örneğin konsol üzerinden kod çalıştırırken, bir kitapçıkta veya eşzamansız olarak yüklenmiş bir komut dosyasında bir şeyler yapmaya çalışıyorsanız. Bu durumda, img.naturalWidth ve img.naturalHeight öğelerinin 0 olup olmadığını kontrol etmek hile yapıyor gibi görünmektedir.

Örneğin, tüm kırık görüntüleri konsoldan yeniden yüklemek için bir kod parçası:

$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}
1
Lea Verou

Bunun en iyi sonuç verdiğini gördüm, herhangi bir görüntü ilk kez yüklenmezse, DOM'dan tamamen kaldırılır. console.clear() işlevinin yürütülmesi, konsol penceresini temiz tutar, çünkü 404 hataları try/catch blokları ile atlanamaz.

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