Офіційний спосіб попросити jQuery зачекати, поки всі зображення завантажуються, перш ніж щось виконати


641

У 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() { }. Тож якщо ви використовуєте цю платформу, ви отримаєте поведінку, яку я шукаю замість правильної поведінки, описаної вище.


3
не $("img").load()працює?
Лукас

1
Думаю, варто згадати, що якщо ви встановите атрибути розмірів, ви можете безпечно виконувати якийсь код у готовій функції, що спирається на ці параметри. За допомогою php ви можете захопити їх за допомогою php.net/manual/en/function.getimagesize.php для завантаження, щоб зберегти їх у db або перед виведенням у браузер.
Алькін

якщо ви хочете щось зробити неймовірною роботою, перегляньте надзвичайно гарну та популярну бібліотеку javascript для завантаження зображень, згадану в цій відповіді нижче stackoverflow.com/a/26458347/759452
Adrien Be

"Тут я прийшов знайти щось, крім офіційного способу".
Леон Пелтьє

Відповіді:


1035

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

Різницю можна побачити в наступному повному HTML-файлі, якщо у вас є jollyrogerJPEG-файли (або інші відповідні):

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

32
присмакує лобом +1 абсолютно це забув. $ (window) .load () не запускається, поки не буде зроблено зображення.
Паоло Бергантіно

10
Я зробив те саме. Навіть, прочитайте відповідь, не знаючи, що це я, і все ще не розумію.
Ріміан

24
Лише зауваження - це, здається, не працює під Chromium (і я припускаю, що Chrome). Здається, що подія $ (window) .ready запускається так само, як $ (document) .ready - до завершення зображень.
Натан Крейз

24
але це $ (window) .load (function ())
TJ-

3
@KyorCode Ви впевнені, що це не лише тому, що зображення в IE були кешовані? Якщо це станеться, вони взагалі не запускають події "завантаження". Ця стаття допомагає обійти цю проблему.
Джеймі Баркер

157

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

Він схожий на $(window).load(function() { .. }), за винятком того, що дозволяє визначити будь-який селектор для перевірки. Якщо ви хочете знати, коли всі зображення в#content (наприклад) завантажені, це плагін для вас.

Він також підтримує завантаження зображень, на які посилається CSS, наприклад background-image,list-style-image і т.д.

waitForImages плагін jQuery

Приклад використання

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

Приклад на jsFiddle .

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


1
Дякую!! $ .load () не працював для мене, але це робить трюк ідеально.
Fraxtil

Я використовую Chrome версії 22.0.1229.94 та цей плагін, і я намагався прочитати зсуви завантажених зображень у програмі waitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...});проте offset.top все ще дорівнює нулю. Чому?
basZero

1
@basZero Важко розповісти без іншого контексту. Будь ласка, поставте питання на сторінці " Випуски ".
alex

Це не працює для мене, коли зображення є кешованими. Чи існує якийсь спосіб вирішення цього питання?
Mandeep Jain

2
Його в основному аналог imagesLoaded, але він працює і з srcsets. Саме те, що я шукав! Чудовий плагін!
Фабіан Шьонер

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

на всякий випадок, коли комусь потрібен приклад використання плагіну BatchImagesLoad
Джонатан

1
Я не маю на увазі ніякої неповаги, але не можна покладатися "просто" на ваше слово щодо надійності вашого плагіна. Як було сказано у Yevgeniy Afanasyevвідповіді у відповіді , imagesLoaded виконує набагато кращу роботу в цьому випадку і висвітлює випадок використання, який ви згадали разом з багатьма іншими кутовими справами (див. Вирішені проблеми github) .
Адрієн Бе

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

13

Жодна з відповідей поки не дала того, що здається найпростішим рішенням.

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

Що приємного в тому, що ви можете змусити його запускати окремі зображення, як тільки вони завантажуються.
Топ Кіт

6

Я рекомендую використовувати imagesLoaded.jsбібліотеку javascript.

Чому б не використовувати jQuery $(window).load()?

Як занепокоєно на /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

Це питання сфери. imagesLoaded дозволяє націлювати набір зображень, тоді як $(window).load()націлює на всі об’єкти - включаючи всі зображення, об’єкти, .js та .css файли та навіть iframe. Швидше за все, завантажені зображення будуть швидше, ніж $(window).load()через те, що націлена на менший набір ресурсів.

Інші вагомі причини використовувати завантажені зображення

  • офіційно підтримується IE8 +
  • ліцензія: Ліцензія MIT
  • залежності: немає
  • вага (мінімізований та gzipped): 7kb мінімізований (легкий!)
  • Завантажити конструктор (допомагає зменшити вагу): немає потреби, вже крихітні
  • на Github: ТАК
  • спільнота та дописувачі: досить великі, 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/


Я з’ясував, що це не працюватиме належним чином, якщо браузер поверне відповідь 304 Not Mofified для зображення, що означає, що зображення є кешованим.
JohnyFree

1

Використовуйте завантажені зображення PAKKAGED 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, і ви побачите проблему.
Адрієн Бе

Хороший момент, я протестував лише Google Chrome та IE-11. Це працювало. Дякую.
Євгеній Афанасьєв

Я додав це питання кросбраузерності в моєму питанні stackoverflow.com/q/26927575 в точці «Те , що ви не можете зробити з imagesloaded», див imagesLoaded відповідного питання на Github github.com/desandro/imagesloaded/issues/121
Adrien Будь

1

Таким чином ви можете виконати дію, коли завантажуються всі зображення всередині тіла або будь-якого іншого контейнера (що залежить від вашого вибору). ЧИСТИЙ ЖУКЕР, не потрібні додатки

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

0

Моє рішення схоже на молоколоко . Написано як функція 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.