jQuery로 이미지가로드되었는지 (오류 없음) 확인


224

jQuery 라이브러리와 함께 JavaScript를 사용하여 정렬되지 않은 목록에 포함 된 이미지 축소판을 조작하고 있습니다. 이미지가로드되면 한 가지 작업을 수행하고 오류가 발생하면 다른 작업을 수행합니다. jQuery load()error()메소드를 이벤트로 사용 하고 있습니다. 이 이벤트 후 jQuery가 이벤트를 등록하기 전에 이미지가 이미로드되지 않았는지 확인하기 위해 이미지 DOM 요소에서 .complete를 확인하십시오.

jQuery가 이벤트를 등록하기 전에 오류가 발생하는 경우를 제외하고는 올바르게 작동합니다. 내가 생각할 수있는 유일한 해결책은 img onerror속성을 사용하여 "플래그"를 전 세계 어딘가에 (또는 노드 자체에) 저장하여 실패했음을 알려주는 것이므로 jQuery는 .complete를 확인할 때 "store / node"를 확인할 수 있습니다.

더 나은 해결책이 있습니까?

편집 : 굵은 요점과 아래에 추가 세부 사항이 추가되었습니다 . 이미지에로드 및 오류 이벤트를 추가 한 후 이미지가 완전한지 (로드 된 경우) 확인하고 있습니다. 그렇게 하면 이벤트가 등록되기 전에 이미지가로드 된 경우에도 여전히 알 수 있습니다. 이벤트 후에 이미지가로드되지 않으면 이벤트가 이미지를 처리합니다. 이것의 문제는 이미지가 이미로드되어 있는지 쉽게 확인할 있지만 대신 오류가 발생했는지 알 수 없다는 것입니다.


jQuery 이벤트는 언제 등록합니까? 어쩌면 일부 코드가 도움이 될 것입니다. :)
okw

많은 코드가 있습니다. 위에서 말한 것은 내가하고있는 일의 매우 간단한 버전입니다. DOM 이로 드 된 후 이벤트를 호출하면 미리보기 이미지에 이벤트를 추가하기 위해 메소드가 호출됩니다.
William

답변:


250

다른 옵션은 메모리 이미지 요소를 작성하고 해당 속성을 원래 이미지 의 원래 속성으로 설정 하여 onload및 / 또는 onerror이벤트 를 트리거하는 것 입니다. 다음은 내가 의미하는 바의 예입니다.srcsrc

$("<img/>")
    .on('load', function() { console.log("image loaded correctly"); })
    .on('error', function() { console.log("error loading image"); })
    .attr("src", $(originalImage).attr("src"))
;

도움이 되었기를 바랍니다!


27
내가 바랐던 것처럼 작동하지 않는 것 같습니다. Chrome에서는 이미지가 이미 캐시에있을 때 문제가있는 것 같습니다. load () 메소드를 트리거하지 않습니다. :(
William

4
어, 맞아. Chrome은 개발하기에 가장 성가신 브라우저입니다. 밝은 곳에서 해결 방법을 찾은 것 같습니다. 이미지 소스를 ""로 설정 한 다음 원래 소스로 다시 돌아가십시오. 답변을 업데이트하겠습니다.
Xavi

1
당신은 넣어한다 .attr선을 한 후.load.error선. 그렇지 않으면 콜백이 추가 되기 전에 이미지가로드되거나 오류가 발생하여 이미지가 호출되지 않을 위험이 있습니다.
callum

19
@Xavi Chrome은 개발하기에 가장 성가신 브라우저가 아니므로 Internet Explorer 7 이하로 개발해보십시오. 이미지로드에 $ _GET 매개 변수를 추가하는 것 외에도 Gromix가 제안한 것처럼 매번 새 이미지를로드합니다.
SSH 이번

10
.load().error()방법은 혼란과 현재 사용되지 사용되는 .on()및 사용 loaderror같은 이벤트를.
Firsh-LetsWP.io

235

순서대로 completenaturalWidth속성을 확인하십시오 .

https://stereochro.me/ideas/detecting-broken-images-js

function IsImageOk(img) {
    // During the onload event, IE correctly identifies any images that
    // weren’t downloaded as not complete. Others should too. Gecko-based
    // browsers act like NS4 in that they report this incorrectly.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth and
    // naturalHeight. These give the true size of the image. If it failed
    // to load, either of these should be zero.
    if (img.naturalWidth === 0) {
        return false;
    }

    // No other way of checking: assume it’s ok.
    return true;
}

1
흥미롭게도, 나는 그 포스트를 더 일찍보고 있었는데 그들이 그들이하고 있다는 것을 몰랐습니다! naturalWidth가 IE에 정의되어 있지 않으므로 IE에 대해 완료됩니다. 지금 확인하려고합니다.
William

3
분명히 이것은 처음에만 안정적으로 작동합니다. 그런 다음 이미지의 src를 변경하면 최소한 Safari 모바일은 naturalWidth 및 complete의 첫 번째 값을 계속보고합니다.
giorgian

5
img.complete && typeof img.naturalWidth! = 'undefined'를 반환합니다. && img.naturalWidth! = 0;
Adrian Seeley

5
@vsync 당신은 아마 이것을 일회성 검사로 사용하고 싶을 것이고 이미지가 아직로드되지 않았다면 "로드"이벤트 핸들러를 설정하십시오. 이 검사를 여러 번 실행하여 CPU를 망치지 않아도됩니다.
Michael Martin-Smucker

2
궁금한 점은 아래 링크 된 imagesLoaded 라이브러리와 거의 동일합니다. 따라서 일회성 사용의 경우 다음을 수행하십시오. github.com/desandro/imagesloaded/blob/master/…
cincodenada

57

element 의 W3C HTML Specification에 대한img 나의 이해를 바탕으로 다음 completenaturalHeight같이 및 속성 의 조합을 사용하여이를 수행 할 수 있어야합니다 .

function imgLoaded(imgElement) {
  return imgElement.complete && imgElement.naturalHeight !== 0;
}

complete속성 스펙에서 :

다음 조건 중 하나라도 해당되면 IDL 속성 완료가 true를 리턴해야합니다.

  • src 속성이 생략되었습니다.
  • 리소스를 가져 오면 네트워킹 작업 소스에서 대기중인 마지막 작업이 대기되었습니다.
  • img 요소는 완전히 사용할 수 있습니다.
  • img 요소가 손상되었습니다.

그렇지 않으면 속성이 false를 반환해야합니다.

따라서 complete이미지로드가 완료되었거나로드하지 못한 경우 true를 반환합니다. 이미지가 성공적으로로드 된 경우 만 원하므로 nauturalHeight속성도 확인해야합니다 .

IDL의 속성 naturalWidthnaturalHeight이미지가 가능, 0 다른 경우, CSS의 픽셀 이미지의 고유 폭과 높이를 반환해야합니다.

그리고 available다음과 같이 정의됩니다.

img는 항상 다음 상태 중 하나입니다.

  • 사용할 수 없음 -사용자 에이전트가 이미지 데이터를 얻지 못했습니다.
  • 부분적으로 사용 가능 -사용자 에이전트가 일부 이미지 데이터를 얻었습니다.
  • 완전 사용 가능 -사용자 에이전트가 모든 이미지 데이터를 확보했으며 최소한 이미지 크기를 사용할 수 있습니다.
  • 손상됨 -사용자 에이전트가 가능한 모든 이미지 데이터를 얻었지만 이미지 크기를 가져 오기에 충분한 이미지를 디코딩 할 수도 없습니다 (예 : 이미지가 손상되었거나 형식이 지원되지 않거나 데이터를 얻을 수 없음) .

img 요소가 부분적으로 사용 가능한 상태이거나 완전히 사용 가능한 상태 인 경우 사용 가능하다고합니다.

따라서 이미지가 "깨진"경우 (로드에 실패한 경우) 사용 가능한 상태가 아닌 깨진 상태 naturalHeight가되므로 0이됩니다.

따라서 imgElement.complete && imgElement.naturalHeight !== 0이미지가 성공적으로로드되었는지 확인 해야합니다.

이에 대한 자세한 내용 img요소 의 W3C HTML 사양 또는 MDN을 참조하십시오 .


1
작동하지 않습니다 이미지가 "content : url"스타일로로드되었습니다
deathangel908

1
브라우저가 자연 높이 / 너비를 0으로보고하므로 SVG 이미지가있는 Firefox에서는 작동하지 않는 것 같습니다. 관련 버그 : bugzilla.mozilla.org/show_bug.cgi?id=1328124
leeb

20

나는 많은 다른 방법을 시도 했고이 방법은 나를 위해 일한 유일한 방법입니다.

//check all images on the page
$('img').each(function(){
    var img = new Image();
    img.onload = function() {
        console.log($(this).attr('src') + ' - done!');
    }
    img.src = $(this).attr('src');
});

모든 이미지가 DOM에로드되고 준비되면 트리거 된 콜백 함수를 추가 할 수도 있습니다. 이것은 동적으로 추가 된 이미지에도 적용됩니다. http://jsfiddle.net/kalmarsh80/nrAPk/


jsfiddle 링크가 깨짐
Alex Karshin

1
위의 흥미로운 읽기를 테스트했으며 소수의 공통 브라우저에서 캐시 / 캐시되지 않은 테스트 사이에서 실패했습니다. 이 답변은 다른 답변과 비슷하지만 지금 구현하고 테스트 한 것입니다. EdgeWin10, IE11Win8.1, Win7IE10, Win7IE9, iOS 10.2 Chrome, iOS 10.2 Safari, mac os 10.12 Chrome, mac os 10.12 Safari, macOS 10.12 Firefox, Google Pixel 7.1, Samsung S5 Android 4.4. addEventListener / removeEventListener도 사용하는 것을 잊지 마십시오. : D
danjah

13

imagesLoaded자바 스크립트 라이브러리를 사용하십시오 .

일반 자바 스크립트와 jQuery 플러그인으로 사용할 수 있습니다.

풍모:

자원


이것은 나를 위해 완벽하게 작동했습니다. function checkImages (imgs) {$ (imgs) .each (function () {$ (imgs) .imagesLoaded () .progress (function (instance, image) {if (image.isLoaded == false) {console.log (image .img.src + '을 찾을 수 없습니다.'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242

1
주요 버그가 많은 공개 문제가있는 것처럼 보이며 개발자는 그 문제를 많이 따르지 않는 것 같습니다. 현재로서는 프로덕션 환경에서 완전히 사용할 수 없습니다.
vsync

3
@vsync 미해결 문제를 읽었습니까? 그는 거의 모든 사람들에게 반응하며, 대부분 다른 사람들이 만나지 못하는 재현 할 수없는 엣지 케이스 인 것 같습니다. 프로덕션 환경에서 문제가 없었습니다.
Josh Harrison

1
예 내가 직접 사용하고 난이 실패 커버 케이스에의 setTimeout 사용할 수 있도록 때때로, 일을하지 않습니다
수직 동기화

imagesLoaded 플러그인을 사용하려는 이유는 다음과 complete같습니다 . 속성이 명확하게 지원되지 않는 것 같습니다. 브라우저 지원과 관련된 신뢰할 수있는 정보 소스를 찾을 수 없습니다. complete속성은 명확한 사양이없는 것 같습니다 : HTML5 사양은 그것을 언급하는 유일한 사양이며 작성 당시 초안 버전입니다. 당신이 사용하는 경우 naturalWidthnaturalHeight만이 이미지가로드 여부를 확인하는 데 사용하는 경우 그래서, 당신이 오래된 브라우저에서 작동하도록 일부 "영리"트릭이 필요 IE9 + 지원을, 당신은 행동이 일치 크로스 브라우저를 확인해야합니다
아드 수

8

페이지의 이미지 요소에서 정보 검색
Chrome 및 Firefox에서
작업 테스트 jsFiddle 작업 (콘솔을 열어 결과보기)

$('img').each(function(){ // selecting all image element on the page

    var img = new Image($(this)); // creating image element

    img.onload = function() { // trigger if the image was loaded
        console.log($(this).attr('src') + ' - done!');
    }

    img.onerror = function() { // trigger if the image wasn't loaded
        console.log($(this).attr('src') + ' - error!');
    }

    img.onAbort = function() { // trigger if the image load was abort
        console.log($(this).attr('src') + ' - abort!');
    }

    img.src = $(this).attr('src'); // pass src to image object

    // log image attributes
    console.log(img.src);
    console.log(img.width);
    console.log(img.height);
    console.log(img.complete);

});

참고 : jQuery를 사용 했는데 이것이 전체 자바 스크립트에서 달성 할 수 있다고 생각했습니다.

나는 여기에서 좋은 정보를 찾습니다 OpenClassRoom- > 이것은 프랑스어 포럼입니다


3

실시간 네트워크 검출기 - 체크 네트워크 상태 페이지를 새로 고침하지 않고 : (이 JQuery와 아니지만, 테스트 및 100 % 작업 : (파이어 폭스 v25.0에서 테스트))

암호:

<script>
 function ImgLoad(myobj){
   var randomNum = Math.round(Math.random() * 10000);
   var oImg=new Image;
   oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
   oImg.onload=function(){alert('Image succesfully loaded!')}
   oImg.onerror=function(){alert('No network connection or image is not available.')}
}
window.onload=ImgLoad();
</script>

<button id="reloadbtn" onclick="ImgLoad();">Again!</button>

연결이 끊어지면 다시 버튼을 누릅니다.

업데이트 1 : 페이지를 새로 고치지 않고 자동 감지 :

<script>
     function ImgLoad(myobj){
       var randomNum = Math.round(Math.random() * 10000);
       var oImg=new Image;
       oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
       oImg.onload=function(){networkstatus_div.innerHTML="";}
       oImg.onerror=function(){networkstatus_div.innerHTML="Service is not available. Please check your Internet connection!";}
}

networkchecker = window.setInterval(function(){window.onload=ImgLoad()},1000);
</script>

<div id="networkstatus_div"></div>

100 %! 프록시 / 방화벽에 의해 이미지 링크가 차단되거나 이미지 서버가 응답하지 않으면 어떻게합니까? 당신은 여전히 ​​네트워크가 작동하고 있습니다 :)
Sen Jacob

서버에서 모든 이미지를 다시로드하여 의도적으로 캐시를 무효화합니다. 따라서 확인을 위해 모든 이미지의 대역폭이 두 배 이상 증가합니다. 또한 이미지가 특정 위치에로드되었는지 여부가 아니라 서버에 이미지가 있는지 확인합니다. 또한 각 이미지가 언제로드되는지 알 수 없습니다.
마리우스 발치 티스

3

이 페이지에서 흥미로운 솔루션을 읽은 후 크롬, IE, Firefox, Safari 및 Opera (모두 Windows에서). 또한 내가 사용한 iPhone / iPad 에뮬레이터에서 작동했습니다.

이 솔루션과 SLaks 및 Noyo의 게시물의 주요 차이점 중 하나는이 솔루션이 주로 naturalWidth 및 naturalHeight 속성을 확인한다는 것입니다. 현재 브라우저 버전 에서이 두 속성이 가장 유용하고 일관된 결과를 제공하는 것으로 나타났습니다.

이 코드는 이미지가 완전히 성공적으로로드되면 TRUE를 반환합니다. 이미지가 아직 완전히로드되지 않았거나로드에 실패한 경우 FALSE를 반환합니다.

한 가지 알아야 할 것은 이미지가 0x0 픽셀 이미지 인 경우이 함수는 FALSE도 반환한다는 것입니다. 그러나 그 이미지는 매우 드물며 0x0 픽셀 이미지가 아직로드되었는지 확인하려는 매우 유용한 경우를 생각할 수 없습니다. :)

먼저 "isLoaded"라는 새로운 함수를 HTMLImageElement 프로토 타입에 연결하여 어떤 이미지 요소에서도 함수를 사용할 수 있습니다.

HTMLImageElement.prototype.isLoaded = function() {

    // See if "naturalWidth" and "naturalHeight" properties are available.
    if (typeof this.naturalWidth == 'number' && typeof this.naturalHeight == 'number')
        return !(this.naturalWidth == 0 && this.naturalHeight == 0);

    // See if "complete" property is available.
    else if (typeof this.complete == 'boolean')
        return this.complete;

    // Fallback behavior: return TRUE.
    else
        return true;

};

그런 다음 이미지의 로딩 상태를 확인해야 할 때마다 "isLoaded"함수를 호출하면됩니다.

if (someImgElement.isLoaded()) {
    // YAY! The image loaded
}
else {
    // Image has not loaded yet
}

SLaks 및 Noyo의 게시물에 대한 조르지 안의 의견에 따르면 SRC 속성을 변경하려는 경우 Safari Mobile에서 한 번만 확인하면이 솔루션을 사용할 수 있습니다. 그러나 기존 이미지 요소에서 SRC 속성을 변경하는 대신 새 SRC 속성으로 이미지 요소를 작성하여이 문제를 해결할 수 있습니다.


2

이것은 위의 방법의 조합을 사용하여 크로스 브라우저를 작동시키는 방법입니다 (dom에 이미지를 동적으로 삽입해야했습니다).

$('#domTarget').html('<img src="" />');

var url = '/some/image/path.png';

$('#domTarget img').load(function(){}).attr('src', url).error(function() {
    if ( isIE ) {
       var thisImg = this;
       setTimeout(function() {
          if ( ! thisImg.complete ) {
             $(thisImg).attr('src', '/web/css/img/picture-broken-url.png');
          }
       },250);
    } else {
       $(this).attr('src', '/web/css/img/picture-broken-url.png');
    }
});

참고 : isIE 변수에 유효한 부울 상태를 제공해야합니다.


2
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

// 또는 플러그인으로

    $.fn.extend({
      isLoaded: function(){
        return this.prop("complete") && this.prop("naturalWidth") !== 0;
      }
    })

// $(".myImage").isLoaded() 

1

.complete 속성은 비표준입니다. 보편적이지 않을 수도 있습니다 ... Firefox 구절 IE에서 다르게 작동하는 것 같습니다. Javascript에 여러 이미지를로드 한 다음 완료되었는지 확인하고 있습니다. Firefox에서는 이것이 잘 작동하는 것 같습니다. IE에서는 이미지가 다른 스레드에로드되는 것처럼 보이지 않습니다. image.src에 대한 할당 사이에 지연이 발생하고 image.complete 속성을 확인할 때만 작동합니다.

image.onload 및 image.onerror 사용도 작동하지 않습니다. 함수가 호출 될 때 어떤 이미지를 말하고 있는지 알기 위해 매개 변수를 전달해야하기 때문입니다. 실제로 동일한 함수의 다른 인스턴스가 아닌 동일한 함수를 전달하는 것처럼 보이기 때문에 실패하는 것처럼 보입니다. 따라서 이미지를 식별하기 위해 전달하는 값은 항상 루프의 마지막 값이됩니다. 이 문제를 해결할 방법을 생각할 수 없습니다.

Safari와 Chrome에서 image.complete가 표시되고 오류 콘솔에 해당 이미지의 404가 표시 되어도 naturalWidth가 설정되었습니다 ...이 이미지를 의도적으로 제거하여 테스트했습니다. 그러나 위의 내용은 Firefox 및 IE에서 잘 작동합니다.


흠, 흥미 롭습니다. 코드 예제를 게시하여 몇 가지를 시도하고 싶습니까?
Xavi

1

이 코드는 브라우저 캐싱 문제를 해결하는 데 도움이되었습니다.

$("#my_image").on('load', function() {

    console.log("image loaded correctly"); 
}).each(function() {

     if($(this).prop('complete')) $(this).load();
});

브라우저 캐시가 비활성화되면이 코드 만 작동하지 않습니다.

$("#my_image").on('load', function() {
     console.log("image loaded correctly"); 
})

작동하게하려면 다음을 추가해야합니다.

.each(function() {
     if($(this).prop('complete')) $(this).load();
});

0

JavaScript코드를 사용하면 이미지가 성공적으로로드되었는지 확인할 수 있습니다.

document.onready = function(e) {
        var imageobj = new Image();
        imageobj.src = document.getElementById('img-id').src;
        if(!imageobj.complete){ 
            alert(imageobj.src+"  -  Not Found");
        }
}

이것을 사용해보십시오


0

이미지와 EventListener를 완전히로드하는 데 많은 문제가있었습니다.

내가 시도한 것이 무엇이든 결과는 신뢰할 수 없었습니다.

그러나 그 해결책을 찾았습니다. 기술적으로 좋지는 않지만 이제는 이미지로드에 실패하지 않았습니다.

제가 한:

                    document.getElementById(currentImgID).addEventListener("load", loadListener1);
                    document.getElementById(currentImgID).addEventListener("load", loadListener2);

                function loadListener1()
                    {
                    // Load again
                    }

                function loadListener2()
                {
                    var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
                    alert("Image loaded");
                }

이미지를 한 번로드하는 대신 처음으로 직접 두 번째로로드하고 둘 다 이벤트 핸들러를 통해 실행됩니다.

모든 두통이 사라졌습니다!


그건 그렇고 : stackoverflow의 너희들은 이미 백 번 이상 나를 도왔다. 이것을 위해 매우 큰 감사합니다!


0

이것은 나를 위해 잘 작동했습니다 :)

$('.progress-image').each(function(){
    var img = new Image();
    img.onload = function() {
        let imgSrc = $(this).attr('src');
        $('.progress-image').each(function(){
            if($(this).attr('src') == imgSrc){
                console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
            }
        })
    }
    img.src = $(this).attr('src');
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.