Comment puis-je vérifier si une image d'arrière-plan est chargée?


154

Je veux définir une image d'arrière-plan sur la balise body, puis exécuter du code - comme ceci:

$('body').css('background-image','http://picture.de/image.png').load(function() {
    alert('Background image done loading');
    // This doesn't work
});

Comment puis-je m'assurer que l'image d'arrière-plan est entièrement chargée?


4
Attribuez simplement la même URL à l' Image()objet qui a un onloadévénement.
Shadow Wizard est une oreille pour vous le

2
assurez-vous d'envelopper l'url css dansurl()
bluescrubbie

Réponses:


274

essaye ça:

$('<img/>').attr('src', 'http://picture.de/image.png').on('load', function() {
   $(this).remove(); // prevent memory leaks as @benweet suggested
   $('body').css('background-image', 'url(http://picture.de/image.png)');
});

cela créera une nouvelle image en mémoire et utilisera l'événement load pour détecter le chargement du src.


10
On dirait que l'image serait chargée deux fois sans raison.
HyderA

49
@gAMBOOKa Ils sont chargés une fois car ils restent dans la mémoire du navigateur. C'est la même chose, lorsque vous placez des images cachées en haut de votre page, puis que vous les définissez en CSS - les images commencent donc à être téléchargées avant le fichier css - cela s'appelle le préchargement.
jcubic

4
Je ne suis pas trop sûr, mais je pense que vous parlez de cache. Je ne pense pas qu'il existe une mémoire de navigateur où les actifs sont stockés. Si vous faites référence au cache, n'oubliez pas que vous ajoutez une requête HTTP supplémentaire et que tous les clients n'ont peut-être pas le cache activé.
HyderA

7
Entrez ceci dans n'importe quelle page contenant jquery: javascript:void($('<img/>').attr('src', 'http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg').load(function() { $('html').css('background-image', 'url(http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg)'); }))et vérifiez les requêtes HTTP dans Firebug. Si j'ai ouvert la page scintillante avec cette image ouverte dans un autre onglet, il ne fait aucune requête HTTP, affichez simplement cette image instantanément. et quand je vide le cache et l'exécute, il y avait une demande.
jcubic

26
Une comparaison entre ce test et celui-ci montre qu'il faut faire appel .remove()à $('<img/>')object pour éviter une fuite de mémoire. Vous devriez voir une consommation de mémoire stable sur le premier test et une augmentation de la mémoire sur le second. Après quelques heures de fonctionnement sur Chrome 28, le premier test prend 80 Mo et le second 270 Mo.
benweet

23

J'ai un plugin jQuery appelé waitForImagesqui peut détecter le téléchargement des images d'arrière-plan.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);

Ce plugin est également idéal pour pouvoir afficher la progression du chargement à l'aide du eachrappel.
Soviut

1
@alex, Comment dois-je vérifier chaque image d'arrière-plan pour chaque élément d'une classe? J'ai essayé mais ne semble pas le faire correctement. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, function (chargé, nombre, succès) {});
Relm

@Relm Vous ne l'utilisez pas correctement. Le deuxième rappel est par image. De plus, delay()ça ne marche pas comme ça.
alex

16

Quelque chose comme ça:

var $div = $('div'),
  bg = $div.css('background-image');
  if (bg) {
    var src = bg.replace(/(^url\()|(\)$|[\"\'])/g, ''),
      $img = $('<img>').attr('src', src).on('load', function() {
        // do something, maybe:
        $div.fadeIn();
      });
  }
});

bonjour ... cela semble fonctionner, même si j'ai mis le bg.replace sur bg.replace( ... , my_src ). Mais ma question est: une fois le $ ('<img>') chargé, que se passe-t-il exactement avec ça <img>... Je veux dire que ce n'est pas vraiment réel - c'est juste un espace réservé factice, non?
dsdsdsdsd

Droite. Le <img>n'est jamais inséré dans le DOM; il est juste utilisé pour "tromper" le navigateur en chargeant le fichier image dans le cache.
Colin

utile si vous ne voulez pas appeler jQuery
vwvan


8

pure solution JS qui ajoutera un préchargeur, définira l'image d'arrière-plan, puis la configurera pour le garbage collection avec son écouteur d'événements :

Version courte:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector("body");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
    bgElement.style.backgroundImage = `url(${imageUrl})`;
    preloaderImg = null;
});

Un peu plus longtemps avec une belle transition d'opacité:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector(".bg-lazy");
bgElement.classList.add("bg-loading");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
  bgElement.classList.remove("bg-loading");
  bgElement.style.backgroundImage = `url(${imageUrl})`;
  preloaderImg = null;
});
.bg-lazy {
  height: 100vh;
  width: 100vw;
  transition: opacity 1s ease-out;
}

.bg-loading {
  opacity: 0;
}
<div class="bg-lazy"></div>


3
Solution sous-estimée.
Tom Thomson le

1
@TomThomson merci Tom, j'ai trouvé que la transition d'image ne fonctionnait pas correctement, je l'
ai corrigée

6

Voici un petit plugin que j'ai créé pour vous permettre de faire exactement cela, il fonctionne également sur plusieurs images d'arrière-plan et plusieurs éléments:

Lire l'article:

http://catmull.uk/code-lab/background-image-loaded/

ou allez directement au code du plugin:

http://catmull.uk/downloads/bg-loaded/bg-loaded.js

Il suffit donc d'inclure le plugin, puis de l'appeler sur l'élément:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded();
</script>

Téléchargez évidemment le plugin et stockez-le sur votre propre hébergement.

Par défaut, il ajoute une classe supplémentaire "chargée par bg" à chaque élément correspondant une fois l'arrière-plan chargé, mais vous pouvez facilement changer cela en lui passant une fonction différente comme celle-ci:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded({
      afterLoaded : function() {
         alert('Background image done loading');
      }
   });
</script>

Voici un codepen démontrant qu'il fonctionne.

http://codepen.io/catmull/pen/Lfcpb


3

J'ai localisé une solution qui fonctionnait mieux pour moi, et qui a l'avantage d'être utilisable avec plusieurs images (cas non illustré dans cet exemple).

D'après la réponse de @ adeneo à cette question :

Si vous avez un élément avec une image d'arrière-plan, comme ceci

<div id="test" style="background-image: url(link/to/image.png)"><div>

Vous pouvez attendre que l'arrière-plan se charge en obtenant l'URL de l'image et en l'utilisant pour un objet image en javascript avec un gestionnaire onload

var src = $('#test').css('background-image');
var url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');

var img = new Image();
img.onload = function() {
    alert('image loaded');
}
img.src = url;
if (img.complete) img.onload();

2

J'ai fait un hack pur javascript pour rendre cela possible.

<div class="my_background_image" style="background-image: url(broken-image.jpg)">
<img class="image_error" src="broken-image.jpg" onerror="this.parentElement.style.display='none';">
</div>

Ou

onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";

css:

.image_error {
    display: none;
}

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.