Wie erstelle ich einen JavaScript-Rückruf, um zu wissen, wann ein Bild geladen wird?


Antworten:


159

.complete + Rückruf

Dies ist eine standardkonforme Methode ohne zusätzliche Abhängigkeiten und wartet nicht länger als nötig:

var img = document.querySelector('img')

function loaded() {
  alert('loaded')
}

if (img.complete) {
  loaded()
} else {
  img.addEventListener('load', loaded)
  img.addEventListener('error', function() {
      alert('error')
  })
}

Quelle: http://www.html5rocks.com/de/tutorials/es6/promises/


4
Kann dies schief gehen, wenn das Bild zwischen dem img.completeAnruf und dem addEventListenerAnruf abgeschlossen ist?
Thomas Ahle

@ ThomasAhle Ich bin kein Experte, aber das scheint möglich. Mal sehen, ob jemand eine Lösung hat.
Ciro Santilli 法轮功 冠状 病. 事件 法轮功

Ich denke, es wäre nur ein Problem für parallelen Code, was die meisten Javascript wahrscheinlich nicht sind ..
Thomas Ahle

4
@ThomasAhle Dies ist nicht möglich, da der Browser das Ladeereignis nur auslöst, wenn die Ereigniswarteschlange gedreht wird. Der loadEreignis-Listener muss sich jedoch in einer elseKlausel befinden, img.completedie vor dem loadAuslösen des Ereignisses wahr werden kann. Wenn dies nicht der Fall wäre, hätten Sie möglicherweise loadedzweimal anrufen können (beachten Sie, dass sich dies relativ wahrscheinlich so ändert, dass es img.completeerst dann wahr wird, wenn das Ereignis eintritt Feuer).
Gsnedders

71

Image.onload () funktioniert oft.

Um es zu verwenden, müssen Sie sicherstellen, dass Sie den Ereignishandler binden, bevor Sie das src-Attribut festlegen.

Verwandte Links:

Anwendungsbeispiel:

    window.onload = function () {

        var logo = document.getElementById('sologo');

        logo.onload = function () {
            alert ("The image has loaded!");		
        };

        setTimeout(function(){
            logo.src = 'https://edmullen.net/test/rc.jpg';         
        }, 5000);
    };
 <html>
    <head>
    <title>Image onload()</title>
    </head>
    <body>

    <img src="#" alt="This image is going to load" id="sologo"/>

    <script type="text/javascript">

    </script>
    </body>
    </html>


26
Zu Ihrer Information: Gemäß der W3C-Spezifikation ist Onload kein gültiges Ereignis für IMG-Elemente. Natürlich unterstützen Browser dies, aber wenn Sie sich für die Spezifikation interessieren und nicht 100% sicher sind, dass alle Browser, auf die Sie abzielen möchten, dies unterstützen, sollten Sie sie überdenken oder zumindest im Auge behalten.
Jason Bunting

3
Warum scheint es eine schlechte Idee zu sein, 5 Sekunden zu warten, um die Quelle einzustellen?
quemeful

8
@quemeful deshalb heißt es "ein Beispiel".
Diego Jancic

3
@JasonBunting Was schaust du dir an, das dich denken lässt, dass die loadVeranstaltung nicht gültig ist? html.spec.whatwg.org/multipage/webappapis.html#handler-onload ist die Definition des onload Ereignishandlers.
Gsnedders

4
@gsnedders - Sie erkennen, ich würde annehmen, dass ich mich beim Schreiben dieses Kommentars auf den bestehenden Standard bezog, nicht auf den, auf den Sie hingewiesen haben, der 4,5 Jahre neuer ist. Hätten Sie damals gefragt, hätte ich vielleicht darauf hinweisen können. Das ist die Natur des Webs, oder? Dinge werden alt oder werden bewegt oder modifiziert usw.
Jason Bunting

20

Sie können die Eigenschaft .complete der Javascript-Bildklasse verwenden.

Ich habe eine Anwendung, in der ich eine Reihe von Bildobjekten in einem Array speichere, die dynamisch zum Bildschirm hinzugefügt werden. Beim Laden schreibe ich Aktualisierungen in ein anderes Div auf der Seite. Hier ist ein Code-Snippet:

var gAllImages = [];

function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
{
    gAllImages = [];

    for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
    {
        var theImage = new Image();
        theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
        gAllImages.push(theImage);

        setTimeout('checkForAllImagesLoaded()', 5);
        window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;

        // make a new div containing that image
        makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
    }
}

function checkForAllImagesLoaded()
{
    for (var i = 0; i < gAllImages.length; i++) {
        if (!gAllImages[i].complete) {
            var percentage = i * 100.0 / (gAllImages.length);
            percentage = percentage.toFixed(0).toString() + ' %';

            userMessagesController.setMessage("loading... " + percentage);
            setTimeout('checkForAllImagesLoaded()', 20);
            return;
        }
    }

    userMessagesController.setMessage(globals.defaultTitle);
}

Ich habe in meiner Arbeit schon einmal ähnlichen Code verwendet. Dies funktioniert gut in allen Browsern.
Gabriel Hurley

2
Das Problem bei der vollständigen Überprüfung besteht darin, dass ab IE9 die OnLoad-Ereignisse ausgelöst werden, bevor alle Bilder geladen werden, und es jetzt schwierig ist, einen Auslöser für die Überprüfungsfunktion zu finden.
Gene Vincent


8

Das Leben ist zu kurz für Fragen.

function waitForImageToLoad(imageElement){
  return new Promise(resolve=>{imageElement.onload = resolve})
}

var myImage = document.getElementById('myImage');
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"

myImage.src = newImageSrc;
waitForImageToLoad(myImage).then(()=>{
  // Image have loaded.
  console.log('Loaded lol')
});
<img id="myImage" src="">


1
Dies ist eine großartige Antwort, aber ich glaube nicht, dass Sie so viel Code benötigen. Sie machen es nur verwirrend, indem Sie das srcmit JS hinzufügen .
Brandon Benefield

1
Zeit ist eine große Einschränkung bei der Programmierung. Meiner Erfahrung nach bietet das Schreiben von lesbarem (wenn auch manchmal langem) Code einen enormen Zeitvorteil.
Idan Beker

Warum sollten Sie den src in einer neuen Variablen speichern, um ihn in der nächsten Zeile zu verwenden? Wenn Kürze Ihr Ziel ist, ist das ein Anti-Muster. myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620macht den Trick.
Josiah

3

Hier ist das jQuery-Äquivalent:

var $img = $('img');

if ($img.length > 0 && !$img.get(0).complete) {
   $img.on('load', triggerAction);
}

function triggerAction() {
   alert('img has been loaded');
}

1

Nicht geeignet für 2008, als die Frage gestellt wurde, aber heutzutage funktioniert das gut für mich:

async function newImageSrc(src) {
  // Get a reference to the image in whatever way suits.
  let image = document.getElementById('image-id');

  // Update the source.
  img.src = src;

  // Wait for it to load.
  await new Promise((resolve) => { image.onload = resolve; });

  // Done!
  console.log('image loaded! do something...');
}

0

Diese Funktionen lösen das Problem. Sie müssen die DrawThumbnailsFunktion implementieren und eine globale Variable zum Speichern der Bilder haben. Ich liebe es, dies mit einem Klassenobjekt zum Laufen zu bringen, das die ThumbnailImageArrayVariable als Mitglied hat, aber ich habe Probleme!

genannt wie in addThumbnailImages(10);

var ThumbnailImageArray = [];

function addThumbnailImages(MaxNumberOfImages)
{
    var imgs = [];

    for (var i=1; i<MaxNumberOfImages; i++)
    {
        imgs.push(i+".jpeg");
    }

    preloadimages(imgs).done(function (images){
            var c=0;

            for(var i=0; i<images.length; i++)
            {
                if(images[i].width >0) 
                {
                    if(c != i)
                        images[c] = images[i];
                    c++;
                }
            }

            images.length = c;

            DrawThumbnails();
        });
}



function preloadimages(arr)
{
    var loadedimages=0
    var postaction=function(){}
    var arr=(typeof arr!="object")? [arr] : arr

    function imageloadpost()
    {
        loadedimages++;
        if (loadedimages==arr.length)
        {
            postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
        }
    };

    for (var i=0; i<arr.length; i++)
    {
        ThumbnailImageArray[i]=new Image();
        ThumbnailImageArray[i].src=arr[i];
        ThumbnailImageArray[i].onload=function(){ imageloadpost();};
        ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
    }
    //return blank object with done() method    
    //remember user defined callback functions to be called when images load
    return  { done:function(f){ postaction=f || postaction } };
}

11
Der größte Teil dieses Codes ist irrelevant, einschließlich Ihrer gesamten addThumbnailImagesFunktion. Reduzieren Sie es auf den entsprechenden Code und ich werde die -1 entfernen.
Justin Morgan

0

Wenn das Ziel darin besteht, das Bild zu formatieren, nachdem der Browser das Bild gerendert hat, sollten Sie:

const img = new Image();
img.src = 'path/to/img.jpg';

img.decode().then(() => {
/* set styles */
/* add img to DOM */ 
});

weil der browser erst loads the compressed version of imagedann decodes itendlich paints. Da es kein Ereignis paintgibt, sollten Sie Ihre Logik ausführen, nachdem der Browser decodeddas img-Tag hat.


-2

Wenn Sie React.js verwenden, können Sie Folgendes tun:

render() {

// ...

<img 
onLoad={() => this.onImgLoad({ item })}
onError={() => this.onImgLoad({ item })}

src={item.src} key={item.key}
ref={item.key} />

// ...}

Wo:

  • - onLoad (...) wird jetzt wie folgt aufgerufen: {src: " https: //......png ", key: "1"} Sie können dies als "key" verwenden, um zu wissen, welche Bilder angezeigt werden ist richtig geladen und welche nicht.
  • - onError (...) ist das gleiche, aber für Fehler.
  • - Das Objekt "item" ist ungefähr so ​​{key: "..", src: ".."}, mit dem Sie die URL und den Schlüssel der Bilder speichern können, um sie in einer Liste von Bildern zu verwenden.

  • Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
    Licensed under cc by-sa 3.0 with attribution required.