Javascript - выполнить после загрузки всех изображений

Прочитав другие вопросы, я подумал

window.onload=...

ответит на мой вопрос. Я пробовал это, но он выполняет код в момент загрузки страницы (не после загрузки изображений).

Если какая-либо разница, изображения поступают из CDN и не являются относительными.

Кто-нибудь знает решение? (Я не использую jQuery)

Ответ 1

Вот быстрый взлом для современных браузеров:

var imgs = document.images,
    len = imgs.length,
    counter = 0;

[].forEach.call( imgs, function( img ) {
    img.addEventListener( 'load', incrementCounter, false );
} );

function incrementCounter() {
    counter++;
    if ( counter === len ) {
        console.log( 'All images loaded!' );
    }
}

Как только все изображения будут загружены, ваша консоль покажет "Все изображения загружены!".

Что делает этот код:

  • Загрузите все изображения в переменную из документа
  • Прокрутка этих изображений
  • Добавить прослушиватель для события "load" на каждом из этих изображений для запуска функции incrementCounter
  • incrementCounter увеличит счетчик
  • Если счетчик достиг длины изображений, это означает, что все они загружены.

Наличие этого кода в кросс-браузере не будет таким сложным, это просто чище, как это.

Ответ 2

Promise Pattern решит эту проблему наилучшим образом, я предоставил if.js библиотеку с открытым исходным кодом для решения проблемы загрузки всех изображений.

function loadImage (src) {
    var deferred = when.defer(),
        img = document.createElement('img');
    img.onload = function () { 
        deferred.resolve(img); 
    };
    img.onerror = function () { 
        deferred.reject(new Error('Image not found: ' + src));
    };
    img.src = src;

    // Return only the promise, so that the caller cannot
    // resolve, reject, or otherwise muck with the original deferred.
    return deferred.promise;
}

function loadImages(srcs) {
    // srcs = array of image src urls

    // Array to hold deferred for each image being loaded
    var deferreds = [];

    // Call loadImage for each src, and push the returned deferred
    // onto the deferreds array
    for(var i = 0, len = srcs.length; i < len; i++) {
        deferreds.push(loadImage(srcs[i]));

        // NOTE: We could push only the promise, but since this array never
        // leaves the loadImages function, it ok to push the whole
        // deferred.  No one can gain access to them.
        // However, if this array were exposed (e.g. via return value),
        // it would be better to push only the promise.
    }

    // Return a new promise that will resolve only when all the
    // promises in deferreds have resolved.
    // NOTE: when.all returns only a promise, not a deferred, so
    // this is safe to expose to the caller.
    return when.all(deferreds);
}

loadImages(imageSrcArray).then(
    function gotEm(imageArray) {
        doFancyStuffWithImages(imageArray);
        return imageArray.length;
    },
    function doh(err) {
        handleError(err);
    }
).then(
    function shout (count) {
        // This will happen after gotEm() and count is the value
        // returned by gotEm()
        alert('see my new ' + count + ' images?');
    }
);

Ответ 3

Использование window.onload не будет работать, потому что оно срабатывает после загрузки страницы, однако изображения не включены в это определение загруженного.

Общим решением является ImagesLoaded плагин jQuery.

Если вы не любите использовать jQuery вообще, вы можете хотя бы попробовать преобразовать этот плагин в чистый Javascript. В 93 важных строках кода и хорошем комментировании это не должно быть трудной задачей.

Ответ 4

У вас может быть событие onload на изображении, которое может вызвать функцию, выполняющую обработку... Что касается обработки, если загружаются все изображения, я не уверен, будет ли работать какой-либо из следующих механизмов:

имеет функцию, которая подсчитывает количество изображений, для которых вызывается onload, если это равно общему числу изображений на вашей странице, то выполните необходимую обработку.

Ответ 5

 <title>Pre Loading...</title>
 </head>

 <style type="text/css" media="screen"> html, body{ margin:0;
 padding:0; overflow:auto; }
 #loading{ position:fixed; width:100%; height:100%; position:absolute; z-index:1; ackground:white url(loader.gif) no-repeat center; }**
 </style>

 <script> function loaded(){
 document.getElementById("loading").style.visibility = "hidden"; }
 </script>

 <body onload="loaded();"> <div id="loading"></div>

 <img id="img" src="avatar8.jpg" title="AVATAR" alt="Picture of Avatar
 movie" />


 </body>

Ответ 6

Немного поздно в игре, но я нашел следующий метод наиболее простым:

function waitForImages () {
  let isLoading = true

  while (isLoading) {
    const loading = [].slice.call(document.images).filter(img => img.complete !== true)
    if (!loading.length > 0) {
      isLoading = true
      return
    }
  }
}

Обратите внимание, что это блокирующий код (полезно, если вы пытаетесь обеспечить загрузку изображений в нечто вроде phantomjs)

Ответ 7

Я собирался предложить то же самое, что сказал Базнья.

Кроме того, еще один возможный вариант, который, возможно, не такой надежный, но простой в обслуживании, - это выбрать самое важное/самое большое изображение и прикрепить событие onload только к одному. Преимущество здесь в том, что вместо изменения кода, если вы позже добавите больше изображений на свою страницу.

Ответ 8

Это прекрасно работает:

$(function() {
 $(window).bind("load", function() {
    // code here
 });
});