Официальный способ попросить jQuery дождаться загрузки всех изображений перед выполнением чего-либо

625

В jQuery, когда вы это делаете:

$(function() {
   alert("DOM is loaded, but images not necessarily all loaded");
});

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

Скажем, хотя мне нужна анимация, и я не хочу, чтобы она работала до загрузки всех изображений. Есть ли официальный способ в jQuery для этого?

Лучше всего использовать <body onload="finished()">, но я действительно не хочу этого делать, если не нужно.

Примечание. В Internet Explorer есть ошибка в jQuery 1.3.1, которая фактически ожидает загрузки всех изображений перед выполнением кода внутри $function() { }. Поэтому, если вы используете эту платформу, вы получите поведение, которое я ищу, вместо правильного поведения, описанного выше.

  • 3
    не работает $("img").load() ?
  • 1
    Я думаю, что стоит упомянуть, что если вы установите атрибуты измерений, вы можете безопасно выполнить некоторый код в готовой функции, которая полагается на эти измерения. С помощью php вы можете получить их с помощью php.net/manual/en/function.getimagesize.php при загрузке, чтобы сохранить их в БД или перед выводом в браузер.
Показать ещё 2 комментария
Теги:

10 ответов

976
Лучший ответ

С помощью jQuery вы используете $(document).ready() для выполнения чего-либо при загрузке DOM и $(window).on("load", handler) для выполнения чего-либо, когда загружаются все другие вещи, например изображения.

Разницу можно увидеть в следующем полном файле HTML, если у вас есть файлы jollyroger JPEG (или другие подходящие):

<html>
    <head>
        <script src="jquery-1.7.1.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                alert ("done");
            });
        </script>
    </head><body>
        Hello
        <img src="jollyroger00.jpg">
        <img src="jollyroger01.jpg">
        // : 100 copies of this
        <img src="jollyroger99.jpg">
    </body>
</html>

При этом перед загрузкой изображений появляется окно предупреждения, поскольку DOM готов к этой точке. Если вы затем измените:

$(document).ready(function() {

в

$(window).on("load", function() {

тогда окно предупреждения не появится до загрузки изображений.

Следовательно, чтобы подождать, пока вся страница будет готова, вы можете использовать что-то вроде:

$(window).on("load", function() {
    // weave your magic here.
});
  • 30
    попахивает лбом +1 полностью забыл это. $ (window) .load () не будет срабатывать, пока изображения не будут созданы.
  • 0
    Спасибо! это сделал На самом деле я не заметил, насколько плохим был этот эффект, пока не проверил локально в Safari на Windows потом стало мучительно очевидно, что мне нужно это сделать. чмокает лоб
Показать ещё 16 комментариев
144

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

Он похож на $(window).load(function() { .. }), за исключением того, что он позволяет определить любой селектор для проверки. Если вы хотите знать, когда загрузились все изображения в #content (например), это плагин для вас.

Он также поддерживает загрузку изображений, указанных в CSS, таких как background-image, list-style-image и т.д.

waitForImages Плагин jQuery

Пример использования

$('selector').waitForImages(function() {
    alert('All images are loaded.');
});

Пример jsFiddle.

Дополнительная документация доступна на странице GitHub.

  • 1
    Спасибо!! $ .load () не работал для меня, но это отлично работает.
  • 0
    Я использую Chrome версии 22.0.1229.94 и этот плагин, и я попытался прочитать смещения из загруженных изображений в пределах waitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...}); Each ('img selector').each(function(index) { var offset = $(this).offset(); ...}); однако, offset.top по-прежнему равен нулю. Зачем?
Показать ещё 8 комментариев
48

$(window).load() будет работать только при первой загрузке страницы. Если вы делаете динамический материал (например: нажмите кнопку, дождитесь загрузки некоторых новых изображений), это не сработает. Для этого вы можете использовать мой плагин:

Демо

Загрузить

/**
 *  Plugin which is applied on a list of img objects and calls
 *  the specified callback function, only when all of them are loaded (or errored).
 *  @author:  H. Yankov (hristo.yankov at gmail dot com)
 *  @version: 1.0.0 (Feb/22/2010)
 *  http://yankov.us
 */

(function($) {
$.fn.batchImageLoad = function(options) {
    var images = $(this);
    var originalTotalImagesCount = images.size();
    var totalImagesCount = originalTotalImagesCount;
    var elementsLoaded = 0;

    // Init
    $.fn.batchImageLoad.defaults = {
        loadingCompleteCallback: null, 
        imageLoadedCallback: null
    }
    var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);

    // Start
    images.each(function() {
        // The image has already been loaded (cached)
        if ($(this)[0].complete) {
            totalImagesCount--;
            if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
        // The image is loading, so attach the listener
        } else {
            $(this).load(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // An image has been loaded
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
            $(this).error(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // The image has errored
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
        }
    });

    // There are no unloaded images
    if (totalImagesCount <= 0)
        if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
};
})(jQuery);
  • 1
    нет возможности скачать это ..
  • 0
    на всякий случай кому-нибудь понадобится пример использования плагина BatchImagesLoad : yankov.us/batchImageLoad
Показать ещё 1 комментарий
19

Для тех, кто хочет получить уведомление о завершении загрузки одного изображения, которое запрашивается после срабатывания $(window).load, вы можете использовать событие load элемента изображения.

например:.

// create a dialog box with an embedded image
var $dialog = $("<div><img src='" + img_url + "' /></div>");

// get the image element (as a jQuery object)
var $imgElement = $dialog.find("img");

// wait for the image to load 
$imgElement.load(function() {
    alert("The image has loaded; width: " + $imgElement.width() + "px");
});
7

Ни один из ответов до сих пор не дал то, что кажется самым простым решением.

$('#image_id').load(
  function () {
    //code here
});
  • 0
    Что в этом хорошего, так это то, что вы можете запустить его для отдельных изображений, как только они загрузятся.
5

Я бы рекомендовал использовать библиотеку javascript imagesLoaded.js.

Почему бы не использовать jQuery $(window).load()?

Как обсуждалось на https://stackoverflow.com/questions/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

Это вопрос сферы. imagesLoaded позволяет вам настроить набор изображений, тогда как $(window).load() нацеливает все активы, включая все изображения, объекты,.js и .css файлы и даже iframe. Скорее всего, imagesLoaded будет срабатывать раньше, чем $(window).load(), потому что он нацелен на меньший набор активов.

Другие веские причины использовать загруженные изображения

  • официально поддерживается IE8 +
  • лицензия: лицензия MIT
  • зависимости: none
  • вес (minified и gzipped): 7kb minified (свет!)
  • скачать строитель (помогает сократить вес): нет необходимости, уже крошечный
  • в Github: YES
  • сообщество и участники: довольно большой, 4000+ участников, хотя только 13 участников
  • история и вклад: стабильный как относительно старый (с 2010 года), но все еще активный проект

Ресурсы

4

С jQuery я прихожу с этим...

$(function() {
    var $img = $('img'),
        totalImg = $img.length;

    var waitImgDone = function() {
        totalImg--;
        if (!totalImg) alert("Images loaded!");
    };

    $('img').each(function() {
        $(this)
            .load(waitImgDone)
            .error(waitImgDone);
    });
});

Демо: http://jsfiddle.net/molokoloco/NWjDb/

  • 0
    Я обнаружил, что это не будет работать должным образом, если браузер возвращает 304 Not Mofified ответ для изображения, означающий, что изображение кэшируется.
1

Таким образом вы можете выполнить действие, когда загружаются все изображения внутри тела или любого другого контейнера (который зависит от вашего выбора). PURE JQUERY, не требуется никаких pluggins.

var counter = 0;
var size = $('img').length;

$("img").load(function() { // many or just one image(w) inside body or any other container
    counter += 1;
    counter === size && $('body').css('background-color', '#fffaaa'); // any action
}).each(function() {
  this.complete && $(this).load();        
});
1

Использовать imagesLoaded PACKAGED v3.1.8 (6.8 Kb при минимизации). Он относительно старый (с 2010 года), но все еще активный проект.

Вы можете найти его на github: https://github.com/desandro/imagesloaded

Их официальный сайт: http://imagesloaded.desandro.com/

Почему это лучше, чем использование:

$(window).load() 

Поскольку вы можете загружать изображения динамически, например: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});
  • 1
    На самом деле загруженные изображения не поддерживают изменение значения атрибута src в разных браузерах. Вы должны каждый раз создавать новый элемент изображения. Попробуйте это на Firefox, и вы увидите, что проблема появляется.
  • 0
    Хороший вопрос, я только тестировал на Google Chrome и IE-11. Это работало. Благодарю.
Показать ещё 1 комментарий
0

Мое решение похоже на molokoloco. Написано как функция jQuery:

$.fn.waitForImages = function (callback) {
    var $img = $('img', this),
        totalImg = $img.length;

    var waitImgLoad = function () {
        totalImg--;
        if (!totalImg) {
            callback();
        }
    };

    $img.each(function () {
        if (this.complete) { 
            waitImgLoad();
        }
    })

    $img.load(waitImgLoad)
        .error(waitImgLoad);
};

Пример:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню