Offizielle Möglichkeit, jQuery zu bitten, auf das Laden aller Bilder zu warten, bevor etwas ausgeführt wird

640

In jQuery, wenn Sie dies tun:

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

Es wartet darauf, dass das DOM geladen wird, und führt Ihren Code aus. Wenn nicht alle Bilder geladen sind, wird der Code trotzdem ausgeführt. Dies ist offensichtlich das, was wir wollen, wenn wir DOM-Inhalte initialisieren, z. B. Elemente ein- oder ausblenden oder Ereignisse anhängen.

Nehmen wir jedoch an, ich möchte eine Animation und möchte nicht, dass sie ausgeführt wird, bis alle Bilder geladen sind. Gibt es in jQuery einen offiziellen Weg, dies zu tun?

Der beste Weg, den ich habe, ist zu benutzen <body onload="finished()">, aber ich möchte das nicht wirklich tun, es sei denn, ich muss.

Hinweis: In jQuery 1.3.1 in Internet Explorer ist ein Fehler aufgetreten, der darauf wartet, dass alle Bilder geladen werden, bevor Code ausgeführt wird $function() { }. Wenn Sie diese Plattform verwenden, erhalten Sie das gesuchte Verhalten anstelle des oben beschriebenen korrekten Verhaltens.

Simon_Weaver
quelle
3
funktioniert nicht $("img").load()?
Lucas
1
Ich denke, es kann erwähnenswert sein, dass Sie, wenn Sie die Dimensionsattribute festlegen, sicher einen Code in der Ready-Funktion ausführen können, der auf diesen Dimensionen basiert. Mit PHP können Sie sie beim Hochladen mit php.net/manual/en/function.getimagesize.php abrufen , um sie in der Datenbank oder vor der Ausgabe im Browser zu speichern.
Alqin
Wenn Sie möchten, dass etwas einen unglaublichen Job macht, dann schauen Sie sich die extrem gute und beliebte Javascript-Bibliothek mit Bildern an, die in dieser Antwort unten aufgeführt ist. stackoverflow.com/a/26458347/759452
Adrien Be
"Hier bin ich gekommen, um etwas anderes als einen offiziellen Weg zu finden."
Léon Pelletier

Antworten:

1034

Mit jQuery können Sie $(document).ready()etwas ausführen, wenn das DOM geladen ist, und $(window).on("load", handler)etwas ausführen, wenn auch alle anderen Dinge geladen sind, wie z. B. die Bilder.

Der Unterschied ist in der folgenden vollständigen HTML-Datei zu sehen, sofern Sie über jollyrogerJPEG-Dateien (oder andere geeignete) verfügen :

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

Damit erscheint das Warnfeld, bevor die Bilder geladen werden, da das DOM zu diesem Zeitpunkt bereit ist. Wenn Sie dann ändern:

$(document).ready(function() {

in:

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

Dann wird das Warnfeld erst angezeigt, nachdem die Bilder geladen wurden.

Um zu warten, bis die gesamte Seite fertig ist, können Sie Folgendes verwenden:

$(window).on("load", function() {
    // weave your magic here.
});
paxdiablo
quelle
32
klatscht auf die Stirn +1 hat das total vergessen. $ (window) .load () wird erst ausgelöst, wenn die Bilder fertig sind.
Paolo Bergantino
10
Ich habe das gleiche getan. Lesen Sie sogar eine Antwort durch, ohne zu wissen, dass ich es war und sie immer noch nicht verstehe.
Rimian
24
Nur eine Anmerkung - dies scheint unter Chromium nicht zu funktionieren (und ich nehme an, Chrome). Das Ereignis $ (window) .ready scheint dasselbe auszulösen wie $ (document) .ready - bevor die Bilder fertiggestellt werden.
Nathan Crause
24
aber es ist $ (Fenster) .load (Funktion ())
TJ
3
@KyorCode Sind Sie sicher, dass die Bilder im IE nicht zwischengespeichert wurden? In diesem Fall wird überhaupt kein "Lade" -Ereignis ausgelöst. Dieser Artikel hilft, dieses Problem zu umgehen.
Jamie Barker
157

Ich habe ein Plugin geschrieben, das Rückrufe auslösen kann, wenn Bilder in Elemente geladen wurden, oder einmal pro geladenem Bild.

Es ist ähnlich $(window).load(function() { .. }), außer dass Sie damit einen zu überprüfenden Selektor definieren können. Wenn Sie nur wissen möchten, wann alle Bilder in #content(zum Beispiel) geladen wurden, ist dies das Plugin für Sie.

Es unterstützt auch das Laden von Bildern in der CSS verweisen, wie background-image, list-style-imageetc.

waitForImages jQuery Plugin

Beispiel Verwendung

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

Beispiel auf jsFiddle .

Weitere Dokumentation finden Sie auf der GitHub-Seite.

Alex
quelle
1
Vielen Dank!! $ .load () hat bei mir nicht funktioniert, aber das macht den Trick perfekt.
Fraxtil
Ich verwende Chrome Version 22.0.1229.94 und dieses Plugin und habe versucht, die Offsets aus den geladenen Bildern in den waitFormImages zu lesen. ('img selector').each(function(index) { var offset = $(this).offset(); ...});Offset.top ist jedoch immer noch Null. Warum?
basZero
1
@basZero Ohne weiteren Kontext schwer zu sagen. Bitte werfen Sie ein Problem auf der Seite Probleme auf .
alex
Es funktioniert nicht für mich, wenn die Bilder cahced sind. Hat jemand eine Problemumgehung dafür?
Mandeep Jain
2
Es ist im Grunde analog zu imagesLoaded, funktioniert aber auch mit srcsets. Genau das, wonach ich gesucht habe! Tolles Plugin!
Fabian Schöner
48

$(window).load()funktioniert nur beim ersten Laden der Seite. Wenn Sie dynamische Dinge tun (Beispiel: Klicken Sie auf die Schaltfläche, warten Sie, bis einige neue Bilder geladen sind), funktioniert dies nicht. Um dies zu erreichen, können Sie mein Plugin verwenden:

Demo

Herunterladen

/**
 *  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
quelle
Nur für den Fall, dass jemand ein Anwendungsbeispiel für das BatchImagesLoad-Plugin benötigt: yankov.us/batchImageLoad
Jonathan Marzullo
1
Ich meine keine Respektlosigkeit, aber man kann sich nicht "nur" auf Ihr Wort bezüglich der Zuverlässigkeit Ihres Plugins verlassen. Wie in Yevgeniy Afanasyevder Antwort erwähnt , leistet imagesLoaded hier viel bessere Arbeit und deckt den von Ihnen erwähnten Anwendungsfall zusammen mit vielen anderen Eckfällen ab (siehe die gelösten Github-Probleme) .
Adrien Be
19

Für diejenigen, die über den Abschluss des Downloads eines einzelnen Bildes benachrichtigt werden möchten, das nach einem $(window).loadBrand angefordert wird, können Sie das loadEreignis des Bildelements verwenden .

z.B:

// 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
quelle
13

Keine der bisherigen Antworten hat die einfachste Lösung geliefert.

$('#image_id').load(
  function () {
    //code here
});
Coz
quelle
Das Schöne daran ist, dass Sie es für einzelne Bilder auslösen können, sobald sie geladen werden.
Top Cat
6

Ich würde empfehlen, imagesLoaded.jsJavascript-Bibliothek zu verwenden.

Warum nicht jQuery's verwenden $(window).load()?

Wie unter /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951 beantwortet

Es ist eine Frage des Umfangs. Mit imagesLoaded können Sie auf eine Reihe von Bildern abzielen, während $(window).load()auf alle Assets - einschließlich aller Bilder, Objekte, .js- und .css-Dateien und sogar iframes - abgezielt wird. Wahrscheinlich wird imagesLoaded früher ausgelöst, als $(window).load()weil es auf eine kleinere Gruppe von Assets abzielt .

Andere gute Gründe für die Verwendung von geladenen Bildern

  • offiziell unterstützt von IE8 +
  • Lizenz: MIT Lizenz
  • Abhängigkeiten: keine
  • Gewicht (minimiert & gezippt): 7kb minimiert (leicht!)
  • Download Builder (hilft beim Abnehmen): keine Notwendigkeit, schon winzig
  • auf Github: JA
  • Community & Mitwirkende: ziemlich groß, über 4000 Mitglieder, obwohl nur 13 Mitwirkende
  • Geschichte & Beiträge: stabil wie relativ alt (seit 2010) aber noch aktives Projekt

Ressourcen

Adrien Be
quelle
4

Mit jQuery komme ich mit diesem ...

$(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
quelle
Ich habe herausgefunden, dass dies nicht richtig funktioniert, wenn der Browser die Antwort 304 Not Mofified für das Bild zurückgibt, was bedeutet, dass das Bild zwischengespeichert ist.
JohnyFree
1

Verwenden Sie imagesLoaded PACKAGED v3.1.8 (6,8 KB, wenn minimiert). Es ist relativ alt (seit 2010), aber immer noch aktives Projekt.

Sie finden es auf github: https://github.com/desandro/imagesloaded

Ihre offizielle Website: http://imagesloaded.desandro.com/

Warum ist es besser als zu verwenden:

$(window).load() 

Weil Sie Bilder möglicherweise dynamisch laden möchten, wie folgt : jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});
Jewgenij Afanasjew
quelle
1
Tatsächlich unterstützt das Laden von Bildern die Änderung des Cross-Browser-Attributwerts src nicht. Sie müssen jedes Mal ein neues Bildelement erstellen. Probieren Sie es in Firefox aus und Sie werden sehen, dass das Problem auftritt.
Adrien Be
Guter Punkt, ich habe bisher nur auf Google Chrome und IE-11 getestet. Es hat funktioniert. Vielen Dank.
Jewgenij Afanasjew
Ich habe dieses browserübergreifende Problem in meiner Frage stackoverflow.com/q/26927575 unter dem Punkt "Was Sie mit geladenen Bildern nicht tun können" hinzugefügt. Weitere Informationen finden Sie im relevanten Problem "imagesLoaded" unter Github github.com/desandro/imagesloaded/issues/121
Adrien Seien Sie
1

Auf diese Weise können Sie eine Aktion ausführen, wenn alle Bilder im Körper oder in einem anderen Container (der von Ihrer Auswahl abhängt) geladen werden. PURE JQUERY, keine Pluggins erforderlich.

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

Meine Lösung ähnelt Molokoloco . Geschrieben als jQuery-Funktion:

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

Beispiel:

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