Oficjalny sposób, aby poprosić jQuery, aby załadował wszystkie obrazy, zanim coś wykona

640

Gdy to zrobisz w jQuery:

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

Oczekuje na załadowanie DOM i wykonuje kod. Jeśli wszystkie obrazy nie zostaną załadowane, nadal wykonuje kod. To jest oczywiście to, czego chcemy, jeśli inicjujemy jakieś elementy DOM, takie jak pokazywanie lub ukrywanie elementów lub dołączanie zdarzeń.

Powiedzmy jednak, że chcę animacji i nie chcę, aby działała, dopóki wszystkie obrazy nie zostaną załadowane. Czy istnieje jQuery w oficjalny sposób?

Najlepszym sposobem jest użycie <body onload="finished()">, ale tak naprawdę nie chcę tego robić, chyba że muszę.

Uwaga: w jQuery 1.3.1 w Internet Explorerze występuje błąd, który faktycznie czeka na załadowanie wszystkich obrazów przed wykonaniem kodu w środku $function() { }. Więc jeśli używasz tej platformy, uzyskasz zachowanie, którego szukam, zamiast poprawnego zachowania opisanego powyżej.

Simon_Weaver
źródło
3
nie $("img").load()działa?
Lucas
1
Myślę, że warto wspomnieć, że jeśli ustawisz atrybuty wymiarów, możesz bezpiecznie wykonać kod w funkcji gotowej, która polega na tych wymiarach. Z php możesz pobrać je za pomocą php.net/manual/en/function.getimagesize.php podczas przesyłania, aby zapisać je w db lub przed wysłaniem do przeglądarki.
Alqin
jeśli chcesz czegoś, co wykonuje niesamowitą robotę, sprawdź niezwykle dobrą i popularną bibliotekę javascript z obrazkami wymienionymi w tej odpowiedzi poniżej stackoverflow.com/a/26458347/759452
Adrien Be
„Przyszedłem tu znaleźć coś poza oficjalnym sposobem”.
Léon Pelletier

Odpowiedzi:

1034

Za pomocą jQuery można $(document).ready()wykonać coś, gdy DOM jest załadowany, i $(window).on("load", handler)wykonać coś, gdy załadowane są również wszystkie inne rzeczy, takie jak obrazy.

Różnicę można zobaczyć w następującym pełnym pliku HTML, pod warunkiem, że masz jollyrogerpliki JPEG (lub inne odpowiednie):

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

Dzięki temu okno alertu pojawia się przed załadowaniem obrazów, ponieważ DOM jest w tym momencie gotowy. Jeśli następnie zmienisz:

$(document).ready(function() {

w:

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

wtedy okno ostrzeżenia pojawi się dopiero po załadowaniu zdjęć.

Dlatego, aby poczekać, aż cała strona będzie gotowa, możesz użyć czegoś takiego:

$(window).on("load", function() {
    // weave your magic here.
});
paxdiablo
źródło
32
klapsy w czoło +1 zupełnie o tym zapomniałem. $ (okno) .load () nie uruchomi się, dopóki obrazy nie zostaną wykonane.
Paolo Bergantino
10
Zrobiłem to samo. Nawet przeczytaj odpowiedź, nie wiedząc, że to ja, i nadal jej nie rozumiem.
Rimian
24
Tylko uwaga - wydaje się, że to nie działa w przypadku Chromium (i przypuszczam, że Chrome). Wydarzenie $ (okno) .ready wydaje się uruchamiać tak samo jak $ (dokument) .ready - przed ukończeniem obrazów.
Nathan Crause
24
ale to $ (okno) .load (funkcja ())
TJ-
3
@KyorCode Czy na pewno nie chodzi tylko o to, że obrazy w IE zostały zapisane w pamięci podręcznej? Jeśli tak się stanie, w ogóle nie wywołają zdarzenia „obciążenia”. Ten artykuł pomaga obejść ten problem.
Jamie Barker
157

Napisałem wtyczkę, która może uruchamiać wywołania zwrotne, gdy obrazy są ładowane w elementach, lub uruchamiane raz na załadowany obraz.

Jest podobny do $(window).load(function() { .. }), z tym wyjątkiem, że pozwala zdefiniować dowolny selektor do sprawdzenia. Jeśli chcesz tylko wiedzieć, kiedy #contentzaładowano wszystkie obrazy (na przykład), jest to wtyczka dla Ciebie.

Wspiera również ładowanie obrazów przywoływanych w CSS, takich jak background-image, list-style-imageitp

waitForImages wtyczka jQuery

Przykładowe użycie

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

Przykład na jsFiddle .

Więcej dokumentacji jest dostępnych na stronie GitHub.

alex
źródło
1
Dziękuję Ci!! $ .load () nie działał dla mnie, ale robi to perfekcyjnie.
Fraxtil 30.09.11
Używam przeglądarki Chrome w wersji 22.0.1229.94 i tej wtyczki i próbowałem odczytać przesunięcia z załadowanych obrazów w funkcji waitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...});jednak offset.top wciąż wynosi zero. Dlaczego?
basZero
1
@basZero Trudno powiedzieć bez większego kontekstu. Podnieś problem na stronie Problemy .
alex
Nie działa dla mnie, gdy obrazy są podzielone. Czy ktoś miałby to obejść?
Mandeep Jain
2
Jest w zasadzie analogiczny do imagesLoaded, ale działa również z srcsetami. Właśnie tego szukałem! Świetna wtyczka!
Fabian Schöner
48

$(window).load()będzie działać tylko przy pierwszym załadowaniu strony. Jeśli wykonujesz dynamiczne czynności (na przykład: kliknij przycisk, poczekaj na załadowanie nowych obrazów), to nie zadziała. Aby to osiągnąć, możesz użyć mojej wtyczki:

Próbny

Pobieranie

/**
 *  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);
Roko C. Buljan
źródło
na wypadek, gdyby ktoś potrzebował przykładu użycia wtyczki BatchImagesLoad
Jonathan Marzullo
1
Mam na myśli brak szacunku, ale nie można polegać „tylko” na słowie dotyczącym niezawodności wtyczki. Jak wspomniano w Yevgeniy Afanasyevodpowiedzi , imagesLoaded wykonuje znacznie lepszą robotę i obejmuje opisany powyżej przypadek użycia wraz z wieloma innymi przypadkami narożnymi (zobacz rozwiązane problemy z github) .
Adrien Be
19

Dla tych, którzy chcą otrzymywać powiadomienia o zakończeniu pobierania pojedynczego obrazu, który zostanie zgłoszony po $(window).loadpożarach, możesz użyć loadzdarzenia elementu obrazu .

na przykład:

// 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");
});
Dan Passaro
źródło
13

Żadna z dotychczasowych odpowiedzi nie dała tego, co wydaje się najprostszym rozwiązaniem.

$('#image_id').load(
  function () {
    //code here
});
Coz
źródło
Zaletą tego jest to, że można go uruchomić w przypadku pojedynczych zdjęć, gdy tylko się załadują.
Top Cat
6

Polecam korzystanie z imagesLoaded.jsbiblioteki javascript.

Dlaczego nie skorzystać z jQuery $(window).load()?

Zgodnie z /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

To kwestia zakresu. imagesLoaded pozwala kierować reklamy na zestaw obrazów, a $(window).load()na wszystkie zasoby - w tym wszystkie obrazy, obiekty, pliki .js i .css, a nawet ramki iframe. Najprawdopodobniej imagesLoaded uruchomi się wcześniej niż $(window).load()dlatego, że jest kierowane na mniejszy zestaw zasobów.

Inne dobre powody, aby używać obrazów załadowanych

  • oficjalnie wspierany przez IE8 +
  • Licencja: Licencja MIT
  • zależności: brak
  • waga (zminimalizowana i zgzipowana): zminimalizowana 7kb (lekka!)
  • Konstruktor pobierania (pomaga zmniejszyć wagę): nie ma potrzeby, już mały
  • na Github: TAK
  • społeczność i współautorzy: dość duża, ponad 4000 członków, chociaż tylko 13 współautorów
  • historia i wkład: stabilny jako stosunkowo stary (od 2010 r.), ale wciąż aktywny projekt

Zasoby

Adrien Be
źródło
4

Z jQuery przychodzę z tym ...

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

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

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

Demo: http://jsfiddle.net/molokoloco/NWjDb/

molokoloco
źródło
Dowiedziałem się, że to nie będzie działać poprawnie, jeśli przeglądarka zwróci 304 Niezmodyfikowana odpowiedź na obraz, co oznacza, że ​​obraz jest buforowany.
JohnyFree,
1

Użyj imagesLoaded PACKAGED v3.1.8 (6,8 Kb po zminimalizowaniu). Jest to stosunkowo stary (od 2010 r.), Ale wciąż aktywny projekt.

Możesz go znaleźć na github: https://github.com/desandro/imagesloaded

Ich oficjalna strona: http://imagesloaded.desandro.com/

Dlaczego jest lepszy niż używanie:

$(window).load() 

Ponieważ możesz chcieć ładować obrazy dynamicznie, w ten sposób: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});
Jewgienij Afanasiew
źródło
1
W rzeczywistości załadowane obrazy nie obsługują zmiany wartości atrybutu src w przeglądarce. Za każdym razem musisz utworzyć nowy element obrazu. Wypróbuj go w przeglądarce Firefox, a zobaczysz problem.
Adrien Be
Dobrze, że testowałem jeszcze tylko na Google Chrome i IE-11. To działało. Dzięki.
Jewgienij Afanasiew
Dodałem ten problem z przeglądarką do mojego pytania stackoverflow.com/q/26927575 w punkcie „Czego nie możesz zrobić z obrazami załadowanymi”, patrz imagesLoaded odpowiedni problem na Github github.com/desandro/imagesloaded/issues/121
Adrien Być
1

W ten sposób możesz wykonać akcję, gdy wszystkie obrazy w ciele lub innym pojemniku (zależnym od twojego wyboru) zostaną załadowane. PURE JQUERY, nie są potrzebne wtyczki.

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();        
});
Mario Medrano
źródło
0

Moje rozwiązanie jest podobne do molokoloco . Zapisane jako funkcja 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);
};

przykład:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
Mariusz Charczuk
źródło