Comment créer un rappel JavaScript pour savoir quand une image est chargée?


Réponses:


159

.complete + rappel

Il s'agit d'une méthode conforme aux normes sans dépendances supplémentaires et n'attend pas plus longtemps que nécessaire:

var img = document.querySelector('img')

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

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

Source: http://www.html5rocks.com/en/tutorials/es6/promises/


4
Cela peut-il mal tourner si l'image se termine entre l' img.completeappel et l' addEventListenerappel?
Thomas Ahle

@ThomasAhle Je ne suis pas un expert, mais cela semble possible. Voyons si quelqu'un a une solution.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Je suppose que ce ne serait un problème que pour le code parallèle, ce que la plupart des javascript ne sont probablement pas ..
Thomas Ahle

4
@ThomasAhle Cela ne peut pas, car le navigateur ne déclenchera l'événement de chargement que lorsque la file d'attente d'événements est lancée. Cela dit, l' loadécouteur d'événements doit être dans une elseclause, comme cela img.completepeut devenir vrai avant que l' loadévénement ne soit déclenché, donc si ce n'était pas le cas, vous auriez pu potentiellement loadedappeler deux fois (notez que cela est relativement susceptible de changer de sorte que cela img.completene devient vrai que lorsque l'événement les feux).
gsnedders

72

Image.onload () fonctionnera souvent.

Pour l'utiliser, vous devez vous assurer de lier le gestionnaire d'événements avant de définir l'attribut src.

Liens connexes:

Exemple d'utilisation:

    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
FYI: Selon les spécifications du W3C, onload n'est pas un événement valide pour les éléments IMG. De toute évidence, les navigateurs le prennent en charge, mais si vous vous souciez de la spécification et n'êtes pas sûr à 100% que tous les navigateurs que vous souhaitez cibler le prennent en charge, vous voudrez peut-être le repenser ou du moins le garder à l'esprit.
Jason Bunting

3
Pourquoi attendre 5 secondes pour définir la source semble-t-il une mauvaise idée?
quemeful

8
@quemeful c'est pourquoi on l'appelle "un exemple".
Diego Jancic

3
@JasonBunting Qu'est-ce que vous regardez qui vous fait penser que l' loadévénement n'est pas valide? html.spec.whatwg.org/multipage/webappapis.html#handler-onload est la définition du onload gestionnaire d'événements.
gsnedders

4
@gsnedders - vous réalisez, je suppose, que lorsque j'ai écrit ce commentaire, je faisais référence à la norme existante, pas à celle que vous avez mentionnée, qui est plus récente de 4,5 ans. Si vous aviez demandé à l'époque, j'aurais peut-être pu le signaler. Telle est la nature du Web, non? Les choses vieillissent ou sont déplacées ou modifiées, etc.
Jason Bunting

20

Vous pouvez utiliser la propriété .complete de la classe d'image Javascript.

J'ai une application où je stocke un certain nombre d'objets Image dans un tableau, qui seront ajoutés dynamiquement à l'écran, et au fur et à mesure qu'ils se chargent, j'écris des mises à jour sur un autre div sur la page. Voici un extrait de code:

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

J'ai déjà utilisé un code similaire dans mon travail. Cela fonctionne bien dans tous les navigateurs.
Gabriel Hurley

2
Le problème avec la vérification terminée est qu'à partir d'IE9, les événements OnLoad sont déclenchés avant que toutes les images ne soient chargées et qu'il est difficile de trouver un déclencheur pour la fonction de vérification maintenant.
Gene Vincent


8

La vie est trop courte pour jquery.

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
C'est une excellente réponse, mais je ne pense pas que vous ayez même besoin de beaucoup de code. Vous donnez juste un air déroutant en ajoutant le srcavec JS.
Brandon Benefield

1
Le temps est une énorme contrainte dans la programmation. D'après mon expérience, l'écriture de code lisible (bien que longtemps) donne un énorme gain de temps.
Idan Beker

Pourquoi stockeriez-vous le src dans une nouvelle variable uniquement pour le consommer sur la ligne suivante? Si la brièveté est votre objectif, c'est un anti-modèle. myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620fait l'affaire.
Josiah

3

Voici l'équivalent de jQuery:

var $img = $('img');

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

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

1

Ne convient pas pour 2008 lorsque la question a été posée, mais ces jours-ci, cela fonctionne bien pour moi:

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

ces fonctions résoudront le problème, vous devez implémenter la DrawThumbnailsfonction et avoir une variable globale pour stocker les images. J'adore faire fonctionner cela avec un objet de classe qui a ThumbnailImageArraycomme variable membre, mais j'ai du mal!

appelé comme dans 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
La plupart de ce code n'est pas pertinent, y compris l'ensemble de votre addThumbnailImagesfonction. Réduisez-le au code pertinent et je supprimerai le -1.
Justin Morgan

0

Si l'objectif est de styliser l'image une fois que le navigateur a rendu l'image, vous devez:

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

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

parce que le navigateur d'abord loads the compressed version of image, puis decodes it, enfin paints. car il n'y a pas d'événement pour paintvous devez exécuter votre logique après que le navigateur ait decodedla balise img.


-2

Si vous utilisez React.js, vous pouvez le faire:

render() {

// ...

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

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

// ...}

Où:

  • - onLoad (...) sera maintenant appelé avec quelque chose comme ceci: {src: " https: //......png ", key: "1"} vous pouvez utiliser ceci comme "clé" pour savoir quelles images est chargé correctement et qui non.
  • - onError (...) c'est pareil mais pour les erreurs.
  • - l'objet "item" est quelque chose comme ceci {key: "..", src: ".."} que vous pouvez utiliser pour stocker l'URL et la clé des images afin de les utiliser dans une liste d'images.

  • En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
    Licensed under cc by-sa 3.0 with attribution required.