jQuery / JavaScript เพื่อแทนที่ภาพที่เสียหาย


546

ฉันมีหน้าเว็บที่มีรูปภาพจำนวนมาก บางครั้งภาพไม่พร้อมใช้งานดังนั้นภาพที่ไม่สมบูรณ์จะปรากฏในเบราว์เซอร์ของลูกค้า

ฉันจะใช้ jQuery เพื่อให้ได้ชุดของภาพกรองไปยังภาพที่แตกแล้วแทนที่ src ได้อย่างไร?


- ฉันคิดว่าการทำเช่นนี้กับ jQuery จะทำได้ง่ายขึ้น แต่มันกลับกลายเป็นเรื่องง่ายกว่าที่จะใช้โซลูชัน JavaScript แบบบริสุทธิ์นั่นคือสิ่งที่จัดหาโดย Prestaul

คำตอบ:


760

จัดการกับ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


132
คุณอาจต้องการล้างข้อมูล onerror ก่อนตั้งค่า src มิฉะนั้นถ้า noimage.gif หายไปคุณอาจท้ายด้วย "stack overflow"
pcorcoran

45
ฉันคิดว่าและเราหวังว่าเราจะย้ายออกจากคุณลักษณะแบบอินไลน์สำหรับกิจกรรมจาวาสคริปต์ ...
redsquare

24
redsquare ... พวกเขาเข้าใจได้อย่างสมบูรณ์แบบเมื่อคุณรอบคอบในการควบคุมพวกเขาและอาจมีประโยชน์เมื่อคุณต้องการให้ markup ของคุณสะท้อนสิ่งที่กำลังจะเกิดขึ้นจริง
นิโคล

2
จุดดี NickC เกี่ยวกับมาร์กอัปที่แสดงว่าเกิดอะไรขึ้นฉันแค่ประจบประแจงเมื่อฉันมองมัน: P
SSH

38
@redsquare ฉันเห็นด้วยอย่างยิ่ง แต่นี่เป็นกรณีพิเศษ Inline เป็นที่เดียวที่คุณสามารถแนบผู้ฟังได้อย่างแน่นอนว่าเหตุการณ์จะไม่เปิดขึ้นก่อนที่ผู้ฟังของคุณจะถูกแนบ หากคุณทำที่ท้ายเอกสารหรือรอให้โหลด DOM คุณอาจพลาดเหตุการณ์ข้อผิดพลาดในบางภาพ คุณไม่ควรแนบตัวจัดการข้อผิดพลาดหลังจากเหตุการณ์ถูกไล่ออก
Prestaul

201

ฉันใช้errorตัวจัดการในตัว:

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

แก้ไข:error()วิธีการจะเลิกในjQuery 1.8และสูงกว่า คุณควรใช้.on("error")แทน:

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

112
หากคุณใช้เทคนิคนี้คุณสามารถใช้วิธี "หนึ่ง" เพื่อหลีกเลี่ยงความต้องการแยกเหตุการณ์: $ ('img'). หนึ่ง ('ข้อผิดพลาด', ฟังก์ชัน () {this.src = 'broken.gif';}) ;
Prestaul

7
+1 แต่คุณต้องยกเลิกการผูกหรือไม่ มันทำงานได้อย่างสวยงามในภาพแบบไดนามิก (เช่นภาพที่สามารถเปลี่ยนเมื่อเลื่อน) หากคุณไม่ผูกมัน
Aximili

15
ฉันคิดว่าถ้าคุณไม่ได้ผูกมันและการอ้างอิง broken.gif src ไม่เคยโหลดไม่ว่าด้วยเหตุผลใดก็ตามสิ่งเลวร้ายอาจเกิดขึ้นในเบราว์เซอร์
travis

4
@travis คุณจะใช้สายนี้ ณ จุดใด มีวิธีใดบ้างที่จะใช้วิธีนี้และให้แน่ใจว่าตัวจัดการของคุณได้รับการแนบก่อนเหตุการณ์ข้อผิดพลาดเกิดขึ้น?
Prestaul

5
นี่คือตัวอย่างของกรณีที่ข้อผิดพลาดเกิดขึ้นก่อนที่จะแนบตัวจัดการเหตุการณ์: jsfiddle.net/zmpGz/1ฉันอยากรู้อยากเห็นอย่างแท้จริงถ้ามีวิธีที่ไม่ปลอดภัยในการแนบตัวจัดการนี้ ...
Prestaul

120

ในกรณีที่มีคนอย่างฉันพยายามแนบerrorเหตุการณ์ไปกับimgแท็กHTML แบบไดนามิกฉันต้องการชี้ให้เห็นว่ามีการจับ:

imgเหตุการณ์ข้อผิดพลาดที่เห็นได้ชัดไม่ได้ปรากฏในเบราว์เซอร์ส่วนใหญ่ตรงกันข้ามกับสิ่งที่มาตรฐานพูด

ดังนั้นสิ่งต่อไปนี้จะไม่ทำงาน :

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

หวังว่านี่จะเป็นประโยชน์กับคนอื่น ฉันหวังว่าฉันจะได้เห็นสิ่งนี้ที่นี่ในหัวข้อนี้ แต่ฉันไม่ได้ ดังนั้นฉันจะเพิ่ม


ไม่ทำงาน ฉันโหลดอิมเมจที่ตายแล้วแบบไดนามิกและผนวกเข้ากับ dom และไม่มีเหตุการณ์ 'ข้อผิดพลาด' เกิดขึ้น
vsync

59

นี่คือโซลูชันแบบสแตนด์อโลน:

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

5
เกือบถูกต้อง ... รูปภาพที่ถูกต้องใน IE จะยังคงกลับมา (typeof (this.naturalWidth) == "undefined") == จริง - ฉันเปลี่ยนคำสั่ง if เป็น (! this.complete || (! $. browser.msie && (พิมพ์ this.naturalWidth == "undefined" || this.naturalWidth == 0))
Sugendran

3
กฎนี้เนื่องจากสามารถตรวจพบภาพที่เสียหายหลังจากโหลดหน้าเว็บ ฉันต้องการสิ่งนี้
Northamerican

@Sugendran $.browserถูกเลิกใช้แล้วและถูกลบออกตอนนี้ใช้การตรวจจับคุณสมบัติแทน (จะซับซ้อนขึ้นในกรณีนี้)
lee penkman

3
แบบสแตนด์อโลน แต่ต้องการ jQuery
Charlie

มันใช้งานได้ดี แต่เมื่อ src ของภาพกลับมา204 No Contentมันจะเป็นภาพที่เสีย
Carson Reinke

35

ฉันเชื่อว่านี่คือสิ่งที่คุณต้องการ: jQuery.Preload

นี่คือตัวอย่างโค้ดจากการสาธิตคุณระบุการโหลดและไม่พบภาพและคุณพร้อมแล้ว:

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

1
jQuery.Preload เป็นปลั๊กอินที่จำเป็นต้องใช้โค้ดตัวอย่าง
แดนลอร์ด

17
ใช่ ... นี่เชื่อมโยงกับคำตอบในบรรทัดแรก
Nick Craver

ขอบคุณ Nick สิ่งนี้ดูเหมือนจะเป็นทางออกที่ดีสำหรับปัญหาที่อายุ 8 ปีขึ้นไปของ Firefox ที่ไม่แสดงรูปภาพแทนรูปภาพที่เสียหาย ยิ่งไปกว่านั้นคุณสามารถทำสิ่งเล็ก ๆ น้อย ๆ ... ขอบคุณอีกครั้ง
klewis

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


1
แก้ไขปัญหาของ onerror ที่ไม่ได้ทำการยิงใน firefox :) ขอบคุณ
ram

19

ในขณะที่ OP กำลังมองหาที่จะมาแทนที่ SRC ฉันมั่นใจว่าหลายคนที่กดปุ่มคำถามนี้อาจต้องการซ่อนภาพที่แตกเท่านั้นซึ่งในกรณีนี้วิธีแก้ปัญหาง่ายๆนี้ทำงานได้ดีสำหรับฉัน

ใช้ Inline JavaScript:

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

ใช้จาวาสคริปต์ภายนอก:

var images = document.querySelectorAll('img');

for (var i = 0; i < images.length; i++) {
  images[i].onerror = function() {
    this.style.display='none';
  }
}
<img src='img.jpg' />

ใช้ JavaScript ภายนอกที่ทันสมัย:

document.querySelectorAll('img').forEach((img) => {
  img.onerror = function() {
    this.style.display = 'none';
  }
});
<img src='img.jpg' />

ดูการสนับสนุนเบราว์เซอร์สำหรับNoteList.forEachและลูกศรฟังก์ชั่น


1
ฉันพบว่านี่เป็นวิธีแก้ปัญหาที่เชื่อถือได้มากที่สุดสำหรับฉันกับปัญหาที่คล้ายกันมาก ฉันค่อนข้างจะไม่แสดงภาพใด ๆ นอกจากแสดงทางเลือกภาพที่เสียหาย ขอบคุณ
pc_

สิ่งนี้เห็นได้ชัดว่าไม่ทำงานเมื่อนโยบายความปลอดภัยของเนื้อหาไม่อนุญาตให้สคริปต์แบบอินไลน์
isherwood

@isherwood จุดที่ดี ฉันได้เพิ่มโซลูชันที่ทำงานผ่านไฟล์ JS ภายนอก
นาธานอาเธอร์

11

นี่เป็นวิธีที่รวดเร็วและสกปรกในการแทนที่ภาพที่เสียหายทั้งหมดและไม่จำเป็นต้องเปลี่ยนรหัส 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"),
            });
        }
  });

9

ฉันไม่พบสคริปต์ที่เหมาะกับความต้องการของฉันดังนั้นฉันจึงทำหน้าที่เรียกซ้ำเพื่อตรวจสอบภาพที่เสียหายและพยายามโหลดซ้ำทุกสี่วินาทีจนกว่าจะได้รับการแก้ไข

ฉัน จำกัด ไว้เพียง 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);
});

แนวคิดที่ดีกับการพยายามโหลดภาพซ้ำ สิ่งนี้มีประโยชน์สำหรับรูปภาพที่อัปโหลด / สร้างอัตโนมัติและเซิร์ฟเวอร์อาจไม่ได้รับ / เสร็จสมบูรณ์ขณะโหลดหน้าเว็บ นั่นเป็นรูปแบบดั้งเดิม บิตที่ไม่สอดคล้องกันเกินไปและไม่ได้อยู่ในรสชาติของฉัน แต่ ...
โจอาคิม

8

นี่คือเทคนิคเส็งเคร็ง แต่รับประกันค่อนข้างมาก:

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

6

คุณสามารถใช้การดึงข้อมูลของ GitHub ได้:

ส่วนหน้า: https://github.com/github/fetch
หรือสำหรับแบ็กเอนด์เวอร์ชัน Node.js: https://github.com/bitinn/node-fetch

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

แก้ไข: วิธีนี้จะแทนที่ XHR และคาดว่าจะได้รับใน Chrome แล้ว สำหรับทุกคนที่อ่านสิ่งนี้ในอนาคตคุณอาจไม่จำเป็นต้องมีห้องสมุดดังกล่าวข้างต้น


6

นี่คือ 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:


while (i--)
โหวตขึ้น

4

โทรดีกว่าโดยใช้

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

เนื่องจากการใช้document.readyไม่จำเป็นต้องหมายความว่าโหลดภาพเท่านั้น HTML ดังนั้นจึงไม่จำเป็นต้องโทรออกล่าช้า


4

ตัวแปรCoffeeScript :

ฉันทำเพื่อแก้ไขปัญหากับ Turbolinks ที่ทำให้วิธีการ .error () ได้รับการเลี้ยงดูใน Firefox บางครั้งแม้ว่าภาพจะอยู่ที่นั่นจริงๆ

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

4

ด้วยการใช้คำตอบของ Prestaulฉันได้เพิ่มการตรวจสอบบางอย่างและฉันชอบที่จะใช้วิธี 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

หากคุณแทรกimgด้วย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)">

ทำไมถึงjavascript: _จำเป็น? เนื่องจากสคริปต์ที่แทรกลงใน DOM ผ่านแท็กสคริปต์innerHTMLจะไม่ทำงานในเวลาที่มีการแทรกดังนั้นคุณต้องชัดเจน


4

ผมพบว่าการโพสต์นี้ในขณะที่กำลังมองหาที่โพสต์ SO อื่น ๆ ด้านล่างนี้เป็นสำเนาของคำตอบที่ฉันให้ไว้

ฉันรู้ว่านี่เป็นเธรดเก่า แต่ React ได้รับความนิยมและบางทีผู้ที่ใช้ React จะมาที่นี่เพื่อค้นหาคำตอบของปัญหาเดียวกัน

ดังนั้นหากคุณกำลังใช้ React คุณสามารถทำสิ่งต่าง ๆ ได้ด้านล่างซึ่งเป็นคำตอบดั้งเดิมที่ Ben Alpert จากทีม React ทำไว้ที่นี่

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

ฉันสร้างซอเพื่อแทนที่ภาพที่เสียหายโดยใช้เหตุการณ์ "onerror" สิ่งนี้อาจช่วยคุณได้

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

นี่คือตัวอย่างการใช้ออบเจ็กต์รูปภาพ HTML5 ที่หุ้มด้วย JQuery เรียกใช้ฟังก์ชันโหลดสำหรับ URL รูปภาพหลักและหากการโหลดนั้นทำให้เกิดข้อผิดพลาดให้แทนที่แอตทริบิวต์ src ของรูปภาพด้วย URL สำรอง

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

เพียว JS งานของฉันคือ: หากภาพ 'bl-Once.png' ว่างเปล่า -> แทรกภาพแรก (ที่ไม่ได้สถานะ 404) จากรายการอาร์เรย์ (ใน dir ปัจจุบัน):

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

อาจจำเป็นต้องได้รับการปรับปรุงให้ดีขึ้น แต่:

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' จาก dir ปัจจุบัน


ฉันเคยใช้ในเว็บไซต์เดียวกัน นี่เป็นเพียงความคิด รหัสจริงของฉันได้รับการปรับปรุง ...
ДмитрийДорогонов

3

ฉันไม่แน่ใจว่ามีวิธีที่ดีกว่านี้หรือไม่ แต่ฉันคิดว่าแฮ็คจะเอามันมาได้คุณสามารถ Ajax โพสต์ไปที่ URL ของ img และแยกคำตอบเพื่อดูว่าภาพกลับมาจริงหรือไม่ หากมันกลับมาเป็น 404 หรือบางอย่างให้เปลี่ยนจาก img แม้ว่าฉันคาดหวังว่าสิ่งนี้จะค่อนข้างช้า


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

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

การอ้างอิง


3

ฉันคิดว่าฉันมีวิธีที่สง่างามมากขึ้นกับคณะผู้แทนเหตุการณ์และการจับภาพเหตุการณ์เมื่อwindow's errorแม้ในขณะที่ภาพสำรองล้มเหลวในการโหลด

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

ประเด็นก็คือ :

  1. ใส่รหัสในheadและดำเนินการเป็นสคริปต์แบบอินไลน์แรก ดังนั้นมันจะฟังข้อผิดพลาดเกิดขึ้นหลังจากสคริปต์

  2. ใช้การจับภาพเหตุการณ์เพื่อตรวจจับข้อผิดพลาดโดยเฉพาะอย่างยิ่งสำหรับเหตุการณ์ที่ไม่ทำให้เกิดฟอง

  3. ใช้การมอบหมายกิจกรรมที่หลีกเลี่ยงการผูกเหตุการณ์ในแต่ละภาพ

  4. ให้imgแอตทริบิวต์ข้อผิดพลาดหลังจากให้ a backup.pngเพื่อหลีกเลี่ยงการหายไปของbackup.pngลูปและอนันต์ที่ตามมาดังนี้:

img ข้อผิดพลาด -> backup.png-> error-> backup.png-> ข้อผิดพลาด -> ,,,,,


นี่คือแอนเวอร์ที่ดีที่สุด สิ่งเดียวที่ฉันอยากจะแนะนำก็คือใช้let isImgErrorHandled = target.src === 'backup.png';เพราะมันลดความซับซ้อนลงเล็กน้อย
Sabo

@ Sabo มีปัญหาเล็กน้อยเพราะเส้นทาง src อาจไม่เท่ากับเส้นทางที่ฉันกำหนด ตัวอย่างเช่นtarget.src='backup.png'แต่ครั้งต่อไปconsole.log(target.src)อาจไม่เป็นbackup.png
xianshenglu

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/


2

สิ่งนี้ทำให้ฉันผิดหวังมานานหลายปี แก้ไข CSS imgของฉันชุดภาพพื้นหลังบน เมื่อรูปภาพแบบไดนามิกsrcไม่โหลดไปที่พื้นหน้าตัวยึดตำแหน่งจะปรากฏบนimgbg ของ นี้ทำงานได้หากภาพของคุณมีขนาดเริ่มต้น (เช่นheight, min-height, widthและ / หรือ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; }
}

2

หากไม่สามารถโหลดภาพได้ (เช่นเนื่องจากไม่มีอยู่ใน URL ที่ให้มา) URL ภาพจะถูกเปลี่ยนเป็นค่าเริ่มต้น

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ. toror ()

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


1

ฉันมีปัญหาเดียวกัน รหัสนี้ทำงานได้ดีในกรณีของฉัน

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

1

บางครั้งการใช้errorเหตุการณ์ไม่เป็นไปได้เช่นเนื่องจากคุณกำลังพยายามทำบางสิ่งบนหน้าเว็บที่โหลดไปแล้วเช่นเมื่อคุณใช้รหัสผ่านคอนโซลคอนโซลคั่นหน้าหรือสคริปต์โหลดแบบอะซิงโครนัส ในกรณีนั้นให้ตรวจสอบimg.naturalWidthและimg.naturalHeightเป็น 0 ดูเหมือนว่าจะหลอกลวง

ตัวอย่างเช่นต่อไปนี้เป็นตัวอย่างเพื่อโหลดภาพที่เสียหายทั้งหมดจากคอนโซล:

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

0

ฉันพบว่าสิ่งนี้ทำงานได้ดีที่สุดหากภาพใดไม่สามารถโหลดได้ในครั้งแรกภาพจะถูกลบออกจาก DOM อย่างสมบูรณ์ การดำเนินการconsole.clear()ทำให้หน้าต่างคอนโซลสะอาดเนื่องจากข้อผิดพลาด 404 ไม่สามารถถูกละเว้นด้วย try / catch blocks

$('img').one('error', function(err) {
    // console.log(JSON.stringify(err, null, 4))
    $(this).remove()
    console.clear()
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.