web-dev-qa-db-fra.com

Comment puis-je déterminer si une image a été chargée à l'aide de Javascript / jQuery?

J'écris du code Javascript pour redimensionner la grande image afin qu'elle tienne dans la fenêtre du navigateur de l'utilisateur. (Je ne contrôle malheureusement pas la taille des images sources.)

Donc, quelque chose comme ceci serait dans le HTML:

<img id="photo"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Est-il possible pour moi de déterminer si l'image src d'une balise img a été téléchargée?

J'ai besoin de cela car je rencontre un problème si $(document).ready() est exécuté avant que le navigateur n'ait chargé l'image. $("#photo").width() et $("#photo").height() renverront la taille de l'espace réservé (le texte alternatif). Dans mon cas, c'est quelque chose comme 134 x 20.

En ce moment, je vérifie si la hauteur de la photo est inférieure à 150, et je suppose que si c'est le cas, c'est tout le texte. Mais c’est tout à fait un bidouillage, et cela casserait si une photo mesure moins de 150 pixels de haut (ce qui est peu probable dans mon cas particulier), ou si le texte de remplacement fait plus de 150 pixels de haut (pourrait éventuellement se produire sur une petite fenêtre du navigateur) .


Edit: Pour ceux qui veulent voir le code:

$(function()
{
  var REAL_WIDTH = $("#photo").width();
  var REAL_HEIGHT = $("#photo").height();

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(REAL_HEIGHT < 150)
    {
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
      if(REAL_HEIGHT < 150)
      {
        //image not loaded.. try again in a quarter-second
        setTimeout(adjust_photo_size, 250);
        return;
      }
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});

Mise à jour: Merci pour les suggestions. Il y a un risque que l'événement ne soit pas déclenché si je définis un rappel pour l'événement $("#photo").load. J'ai donc défini un événement onLoad directement sur la balise image. Pour mémoire, voici le code avec lequel j'ai fini par aller:

<img id="photo"
     onload="photoLoaded();"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Puis en Javascript:

//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
{
  isPhotoLoaded = true;
}

$(function()
{
  //Hides scrollbars, so we can resize properly.  Set with JS instead of
  //  CSS so that page doesn't break with JS disabled.
  $("body").css("overflow", "hidden");

  var REAL_WIDTH = -1;
  var REAL_HEIGHT = -1;

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(!isPhotoLoaded)
    {
      //image not loaded.. try again in a quarter-second
      setTimeout(adjust_photo_size, 250);
      return;
    }
    else if(REAL_WIDTH < 0)
    {
      //first time in this function since photo loaded
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});
83
Kip

Ajoutez un écouteur d'événement ou faites en sorte que l'image s'annonce avec onload. Ensuite, déterminez les dimensions à partir de là.

<img id="photo"
     onload='loaded(this.id)'
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

En utilisant le jquery data store , vous pouvez définir un état "chargé".

<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" />

Alors ailleurs tu peux faire:

if ($('#myimage').data('loaded')) {
    // loaded, so do stuff
}
14
Mike Fogel

La bonne réponse est d'utiliser event.special.load

Il est possible que l'événement de chargement ne soit pas déclenché si l'image est chargée à partir du cache du navigateur. Pour tenir compte de cette possibilité, nous pouvons utiliser un événement de chargement spécial qui se déclenche immédiatement si l'image est prête. event.special.load est actuellement disponible en tant que plugin.

Selon la documentation sur . Load ()

9
Evan Carroll

Vous voulez faire ce que Allain a dit, mais sachez que parfois l'image est chargée avant d'être prête, ce qui signifie que votre gestionnaire de charge ne se déclenchera pas. Le meilleur moyen est de faire ce que dit Allain, mais définissez le code source de l’image avec javascript après la connexion du gestionnaire de chargement. De cette façon, vous pouvez garantir qu'il se déclenche.

En termes d'accessibilité, votre site fonctionnera-t-il toujours pour les personnes sans javascript? Vous voudrez peut-être attribuer le src correct à la balise img, attacher votre gestionnaire prêt à exécuter dom pour exécuter votre js: effacez le src de l'image (attribuez-lui une hauteur fixe et une hauteur avec css pour éviter le scintillement de la page), puis définissez votre gestionnaire de chargement img, puis réinitialisez le src dans le bon fichier. De cette façon, vous couvrez toutes les bases :)

5
Andrew Bullock

Selon l'un des commentaires récents à votre question initiale

$(function() {

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()  {
    if (!$("#photo").get(0).complete) {
       $("#photo").load(function() {
          adjust_photo_size();
       });
    } else {
      ... 
    }
});

Avertissement Cette réponse pourrait causer une boucle sérieuse dans ie8 et les versions inférieures, car img.complete n'est pas toujours correctement défini par le navigateur. Si vous devez prendre en charge ie8, utilisez un indicateur pour vous rappeler que l'image est chargée.

4
commonpike

Essayez quelque chose comme:

$("#photo").load(function() {
    alert("Hello from Image");
});
3
Allain Lalonde

J'ai trouvé cela a fonctionné pour moi

document.querySelector("img").addEventListener("load", function() { alert('onload!'); });

Tout le mérite revient à Frank Schwieterman, qui a commenté la réponse acceptée. Je devais mettre ça ici, c'est trop précieux ...

2
Armand

Des commentaires sur celui-ci?

...

doShow = function(){
  if($('#img_id').attr('complete')){
    alert('Image is loaded!');
  } else {
    window.setTimeout('doShow()',100);
  }
};

$('#img_id').attr('src','image.jpg');

doShow();

...

On dirait que ça marche partout ...

2
Jay

Il existe un plugin jQuery appelé "imagesLoaded" qui fournit une méthode compatible avec plusieurs navigateurs pour vérifier si les images d'un élément ont été chargées.

Site: https://github.com/desandro/imagesloaded/

Utilisation pour un conteneur contenant de nombreuses images:

$('container').imagesLoaded(function(){
 console.log("I loaded!");
})

Le plugin est génial:

  1. fonctionne pour vérifier un conteneur avec de nombreuses images à l'intérieur
  2. fonctionne pour vérifier un img pour voir s'il a été chargé
2
jay

Je viens de créer une fonction jQuery pour charger une image à l'aide de jQuerys Deferred Object , ce qui permet de réagir très facilement à l'événement load/error:

$.fn.extend({
    loadImg: function(url, timeout) {
        // init deferred object
        var defer = $.Deferred(),
            $img = this,
            img = $img.get(0),
            timer = null;

        // define load and error events BEFORE setting the src
        // otherwise IE might fire the event before listening to it
        $img.load(function(e) {
            var that = this;
            // defer this check in order to let IE catch the right image size
            window.setTimeout(function() {
                // make sure the width and height are > 0
                ((that.width > 0 && that.height > 0) ? 
                    defer.resolveWith : 
                    defer.rejectWith)($img);
            }, 1);
        }).error(function(e) {
            defer.rejectWith($img);
        });

        // start loading the image
        img.src = url;

        // check if it's already in the cache
        if (img.complete) {
            defer.resolveWith($img);
        } else if (0 !== timeout) {
            // add a timeout, by default 15 seconds
            timer = window.setTimeout(function() {
                defer.rejectWith($img);
            }, timeout || 15000);
        }

        // return the promise of the deferred object
        return defer.promise().always(function() {
            // stop the timeout timer
            window.clearTimeout(timer);
            timer = null;
            // unbind the load and error event
            this.off("load error");
        });
    }
});

Utilisation:

var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png')
.done(function() {
    alert('image loaded');
    $('body').append(this);
}).fail(function(){
    alert('image failed');
});

Voir le travail à: http://jsfiddle.net/roberkules/AdWZj/

1
roberkules

Cette fonction vérifie si une image est chargée en fonction de ses dimensions mesurables. Cette technique est utile si votre script s'exécute après le chargement de certaines images.

imageLoaded = function(node) {
    var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth;
    var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight;
    return w+h > 0 ? true : false;
};
1
Ralph Ritoch

Nous avons développé une page où il a chargé un certain nombre d'images, puis exécuté d'autres fonctions uniquement après le chargement de l'image. C'était un site occupé qui générait beaucoup de trafic. Il semble que le script simple suivant fonctionne sur pratiquement tous les navigateurs:

$(elem).onload = function() {
    doSomething();
}

MAIS CECI IS UN PROBLÈME POTENTIEL POUR IE9!

Le SEUL navigateur sur lequel nous avons signalé des problèmes est IE9. Sommes-nous pas surpris? Il semble que le meilleur moyen de résoudre le problème consiste à ne pas affecter de code source à l'image tant que la fonction onload n'a pas été définie, comme suit:

$(elem).onload = function() {
    doSomething();
}
$(elem).attr('src','theimage.png');

Il semble que IE 9 ne lançera parfois pas l'événement onload pour quelque raison que ce soit. D'autres solutions sur cette page (comme celle d'Evan Carroll, par exemple) ne l'ont toujours pas été. Logiquement, cela vérifiait si l’état de chargement était déjà réussi et déclenchait la fonction et si ce n’était pas le cas, puis définissait le gestionnaire de chargement, mais nous avons quand même démontré que nous pouvions démontrer que l’image pouvait se charger entre ces deux lignes. js apparaissant ainsi non chargé sur la première ligne puis chargé avant que le gestionnaire de chargement ne soit défini.

Nous avons constaté que le meilleur moyen d'obtenir ce que vous voulez est de ne pas définir le src de l'image tant que vous n'avez pas défini le déclencheur d'événement onload.

Nous venons tout juste de cesser de supporter IE8 et je ne peux donc pas parler des versions antérieures à IE9, sinon de tous les autres navigateurs utilisés sur le site - IE10 et 11, ainsi que de Firefox, Chrome, Opera, Safari, etc. les navigateurs mobiles utilisaient - configurer le src avant d’attribuer le gestionnaire onload n’était même pas un problème.

0
Octopus

Puis-je suggérer une solution CSS pure?

Juste avoir un Div que vous voulez montrer l'image po Définir l'image comme arrière-plan. Ensuite, avoir la propriété background-size: cover ou background-size: contain en fonction de vos souhaits.

cover recadrera l'image jusqu'à ce que les petits côtés recouvrent la boîte. contain gardera l'image entière à l'intérieur du div, vous laissant des espaces sur les côtés.

Vérifiez l'extrait ci-dessous.

div {
  height: 300px;
  width: 300px;
  border: 3px dashed grey;
  background-position: center;
  background-repeat: no-repeat;
}

.cover-image {
  background-size: cover;
}

.contain-image {
  background-size: contain;
}
<div class="cover-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
<br/>
<div class="contain-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
0
arunwithasmile