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

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

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

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

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

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

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

10 ответов


С jQuery вы используете $(document).ready() выполнить что-то, когда дом загружается и $(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.
});

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

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

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

waitForImages jQuery плагин

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

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

пример на jsFiddle.

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


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

для тех, кто хочет получать уведомления о завершении загрузки одного изображения, которое запрашивается после $(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");
});

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

$('#image_id').load(
  function () {
    //code here
});

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

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

как ansered дальше https://stackoverflow.com/questions/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

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

другие веские причины использовать imagesloaded

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

ресурсы


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


используйте IMAGESLOADED PACKAGED v3.1.8 (6,8 КБ при минимизации). Он относительно старый (с 2010 года), но все еще активный проект.

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

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

почему это лучше, чем через:

$(window).load() 

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

$('#button').click(function(){
    $('#image').attr('src', '...');
});

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

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

мое решение похоже на 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>