it-swarm-id.com

jQuery / JavaScript untuk mengganti gambar yang rusak

Saya memiliki halaman web yang mencakup banyak gambar. Terkadang gambar tidak tersedia, jadi gambar yang rusak ditampilkan di browser klien.

Bagaimana cara menggunakan jQuery untuk mendapatkan set gambar, memfilternya ke gambar yang rusak kemudian mengganti src?


--Saya pikir akan lebih mudah untuk melakukan ini dengan jQuery, tetapi ternyata lebih mudah untuk hanya menggunakan solusi JavaScript murni, yaitu, yang disediakan oleh Prestaul.

516
Dan Lord

Tangani acara onError agar gambar dipindahkan ulang sumbernya menggunakan JavaScript:

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

Atau tanpa fungsi JavaScript:

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

Tabel kompatibilitas berikut mencantumkan browser yang mendukung fasilitas kesalahan:

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

714
Prestaul

Saya menggunakan handler error bawaan:

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

Edit: Metode error() tidak digunakan lagi dalam 1.8 dan lebih tinggi. Sebagai gantinya, Anda harus menggunakan .on("error") sebagai gantinya:

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

Jika seseorang seperti saya, mencoba untuk melampirkan acara error ke tag HTML img dinamis, saya ingin menunjukkan bahwa, ada masalah:

Tampaknya peristiwa kesalahan imgjangan gelembung di sebagian besar browser, bertentangan dengan apa yang standar katakan .

Jadi, sesuatu seperti yang berikut ini akan tidak berfungsi :

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

Semoga ini bisa membantu orang lain. Saya berharap saya telah melihat ini di sini di utas ini. Tapi saya tidak melakukannya. Jadi, saya menambahkannya

114
mouad

Ini adalah solusi mandiri:

$(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

Saya yakin inilah yang Anda cari: jQuery.Preload

Berikut ini contoh kode dari demo, Anda menentukan pemuatan dan tidak menemukan gambar dan Anda siap:

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

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

23
Mohamad

Berikut adalah cara cepat dan kotor untuk mengganti semua gambar yang rusak, dan tidak perlu mengubah kode HTML;)

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

Sementara OP ingin mengganti SRC, saya yakin banyak orang yang memukul pertanyaan ini mungkin hanya ingin menyembunyikan gambar yang rusak, dalam hal ini solusi sederhana ini bekerja sangat baik untuk saya:

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

Saya tidak dapat menemukan skrip yang sesuai dengan kebutuhan saya, jadi saya membuat fungsi rekursif untuk memeriksa gambar yang rusak dan berusaha memuatnya kembali setiap empat detik hingga diperbaiki.

Saya membatasinya hingga 10 upaya seolah-olah itu tidak dimuat maka gambar mungkin tidak ada di server dan fungsinya akan memasuki infinite loop. Saya masih mengujinya. Jangan ragu untuk meng-tweak-nya :)

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

Ini adalah teknik yang jelek, tapi cukup dijamin:

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

Ini JavaScript, harus kompatibel lintas browser, dan dikirim tanpa markup jelek 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

Anda dapat menggunakan pengambilan GitHub sendiri untuk ini:

Frontend: https://github.com/github/fetch
atau untuk Backend, versi Node.js: https://github.com/bitinn/node-fetch

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

Sunting: Metode ini akan menggantikan XHR dan konon sudah ada di Chrome. Bagi siapa pun yang membaca ini di masa mendatang, Anda mungkin tidak perlu menyertakan perpustakaan yang disebutkan di atas.

5
BarryMode

Jika Anda telah memasukkan img Anda dengan innerHTML, seperti: $("div").innerHTML = <img src="wrong-uri">, Anda dapat memuat gambar lain jika gagal melakukannya, misalnya, ini:

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

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

Mengapa javascript: _needed? Karena skrip yang disuntikkan ke DOM melalui tag skrip di innerHTML tidak dijalankan pada saat disuntikkan, jadi Anda harus eksplisit.

4
horro

Berikut adalah contoh menggunakan objek Gambar HTML5 yang dibungkus oleh JQuery. Panggil fungsi memuat untuk URL gambar utama dan jika memuat itu menyebabkan kesalahan, ganti atribut src gambar dengan URL cadangan.

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

Saya membuat biola untuk mengganti gambar yang rusak menggunakan acara "onerror". Ini dapat membantu Anda.

    //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

Dengan menggunakan jawaban Prestaul , saya menambahkan beberapa cek dan saya lebih suka menggunakan cara 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;
}
4
trante

Lebih baik menggunakan panggilan

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

Karena menggunakan document.ready tidak perlu menyiratkan bahwa gambar dimuat, hanya HTML. Dengan demikian, tidak perlu untuk panggilan yang tertunda.

4
Shade

CoffeeScript varian:

Saya membuatnya untuk memperbaiki masalah dengan Turbolinks yang menyebabkan metode .error () muncul di Firefox kadang-kadang meskipun gambarnya benar-benar ada.

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

JS murni. Tugas saya adalah: jika gambar 'bl-once.png' kosong -> masukkan yang pertama (yang tidak memiliki status 404) gambar dari daftar array (dalam direktori saat ini):

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

Mungkin perlu ditingkatkan, tetapi:

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

                }
            }
        }

    };

Jadi, itu akan memasukkan 'diperlukan.png' yang benar ke src saya atau 'no-image.png' dari dir saat ini.

Saya menemukan posting ini sambil melihat ini _ _ lainnyaSO posting . Di bawah ini adalah salinan dari jawaban yang saya berikan di sana.

Saya tahu ini adalah utas lama, tetapi Bereaksi menjadi populer dan, mungkin, seseorang yang menggunakan Bereaksi akan datang ke sini mencari jawaban untuk masalah yang sama.

Jadi, jika Anda menggunakan React, Anda dapat melakukan sesuatu seperti di bawah ini, yang merupakan jawaban asli yang diberikan oleh Ben Alpert dari tim React di sini

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

referensi

3
Nabi K.A.Z.

Saya memecahkan masalah saya dengan dua fungsi sederhana ini:

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

Saya tidak yakin apakah ada cara yang lebih baik, tapi saya bisa memikirkan hack untuk mendapatkannya - Anda bisa Ajax memposting ke URL img, dan mengurai respons untuk melihat apakah gambar benar-benar kembali. Jika kembali sebagai 404 atau sesuatu, maka tukar keluar img. Meskipun saya berharap ini sangat lambat.

3
Chii

Ini telah membuat saya frustasi selama bertahun-tahun. Perbaikan CSS saya menetapkan gambar latar belakang pada img. Saat gambar dinamis src tidak dimuat ke latar depan, placeholder terlihat di b__ img. Ini berfungsi jika gambar Anda memiliki ukuran default (mis. height, min-height, width dan/atau min-width).

Anda akan melihat ikon gambar yang rusak tetapi ini merupakan peningkatan. Diuji ke IE9 berhasil. iOS Safari dan Chrome bahkan tidak menampilkan ikon yang rusak.

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

Tambahkan sedikit animasi untuk memberi src waktu untuk memuat tanpa flicker latar belakang. Chrome memudar di latar belakang dengan lancar tetapi desktop Safari tidak.

.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

Saya pikir saya memiliki cara yang lebih elegan dengan delegasi acara dan acara menangkap di window's error bahkan ketika gambar cadangan gagal dimuat.

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

Intinya adalah :

  1. Masukkan kode ke dalam head dan dieksekusi sebagai skrip inline pertama. Jadi, itu akan mendengarkan kesalahan yang terjadi setelah skrip.

  2. Gunakan menangkap peristiwa untuk menangkap kesalahan, terutama untuk peristiwa yang tidak menggelembung.

  3. Gunakan delegasi acara yang menghindari peristiwa mengikat pada setiap gambar.

  4. Berikan elemen img atribut atribut setelah memberi mereka backup.png untuk menghindari hilangnya backup.png dan loop tak terbatas berikutnya seperti di bawah ini:

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

2
xianshenglu

Jika gambar tidak dapat dimuat (misalnya, karena tidak ada di URL yang disediakan), URL gambar akan diubah menjadi default,

Untuk informasi lebih lanjut tentang . 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] || ''; });
    });
};

Anda dapat melewati jalur placeholder dan mengakses semua properti dari objek gambar yang gagal melalui $*:

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

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

2
yckart

Saya mendapat masalah yang sama. Kode ini berfungsi dengan baik pada kasus saya.

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

Terkadang menggunakan acara error tidak layak, mis. karena Anda mencoba melakukan sesuatu pada halaman yang sudah dimuat, seperti ketika Anda menjalankan kode melalui konsol, bookmarklet, atau skrip yang dimuat secara tidak sinkron. Dalam hal ini, memeriksa apakah img.naturalWidth dan img.naturalHeight adalah 0 sepertinya berhasil.

Misalnya, inilah cuplikan untuk memuat ulang semua gambar yang rusak dari konsol:

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

Saya menemukan ini bekerja paling baik, jika ada gambar gagal memuat pertama kali, itu sepenuhnya dihapus dari DOM. Menjalankan console.clear() menjaga jendela konsol tetap bersih, karena kesalahan 404 tidak dapat dihilangkan dengan blok coba/tangkap.

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