Comment charger des images dynamiquement (ou paresseusement) lorsque les utilisateurs les font défiler dans la vue

97

J'ai remarqué cela dans de nombreux sites Web "modernes" (par exemple, recherche d'images sur facebook et google) où les images sous le pli se chargent uniquement lorsque l'utilisateur fait défiler la page suffisamment pour les amener dans la zone de visualisation visible ( sur la source de la vue, la page montre X nombre de <img>balises mais elles ne sont pas récupérées directement du serveur ). Comment s'appelle cette technique, comment ça marche et dans combien de navigateurs ça marche. Et existe-t-il un plugin jQuery qui peut atteindre ce comportement avec un minimum de codage.

Éditer

Bonus: quelqu'un peut-il expliquer s'il y a un événement "onScrolledIntoView" ou similaire pour les éléments HTML. Sinon, comment fonctionnent ces plugins?

Salman A
la source
Avez-vous besoin uniquement d'un chargement paresseux d'image? Si vous avez besoin d'un chargement paresseux de contenu, le plugin de défilement infini est la bonne réponse
soju
@rsp @jwegner @Nicholas suis désolé, mais ce n'est pas ce que demande Salman.
Alec Smart
@soju: Je ne suis intéressé que par les images à chargement différé; mais je pourrais envisager d'autres possibilités dans un futur (assez lointain).
Salman A
21
Vous vous demandez pourquoi le comportement par défaut d'un navigateur n'est pas de charger uniquement des images visibles. Imaginez combien de bande passante aurait pu être économisée au cours des 18 dernières années si tel était le cas!
Matthew Lock
2
Bien que je comprenne la raison du chargement paresseux ... Je ne peux honnêtement pas le supporter lorsque je visite un site qui utilise cette méthode. Le clignotement des images me rend fou! :)
Booski

Réponses:

64

Certaines des réponses ici sont pour une page infinie. Ce que Salman demande, c'est le chargement paresseux des images.

Brancher

Démo

EDIT: Comment fonctionnent ces plugins?

Ceci est une explication simplifiée:

  1. Trouvez la taille de la fenêtre et trouvez la position de toutes les images et leurs tailles
  2. Si l'image n'est pas dans la taille de la fenêtre, remplacez-la par un espace réservé de même taille
  3. Lorsque l'utilisateur fait défiler vers le bas et que la position de l'image <défilement + hauteur de la fenêtre, l'image est chargée
Alec Smart
la source
En application, ne fonctionneraient-ils pas de la même manière? Un défilement infini sur une seule colonne d'images équivaudrait à un chargement paresseux, non? Peut-être que je suis confus.
jwegner
1
@jwegner Infinite scroll vous permet d'ajouter de nouveaux éléments au bas de la page lorsque l'utilisateur atteint (ou s'approche) du bas. Les images chargées paresseusement peuvent avoir des espaces réservés de mêmes dimensions sur la page, avec les images elles-mêmes chargées sur le défilement. Ainsi, ce dernier pourrait se charger paresseusement sans affecter la mise en page.
Annika Backstrom
Cela fonctionne bien sur les navigateurs de bureau et iOS mais ne fonctionne pas sur Android (y compris 3.x / 4.x). Une idée pourquoi? l'événement de défilement n'est-il pas pris en charge?
lahsrah
J'étais en train de parcourir la documentation de ce plugin et cela semble assez génial. Je vais l'utiliser sur mon prochain projet.
The Muffin Man
voici un plugin associé, qui fonctionne probablement à peu près de la même manière: afarkas.github.io/lazysizes sauf que je pense qu'il est beaucoup plus robuste et utilise plus de ce qui existe déjà (pas besoin d'espace réservé, par exemple, mais vous pouvez l'avoir si vous vouloir).
cregox
10

Dave Artz d'AOL a donné une excellente conférence sur l'optimisation à jQuery Conference Boston l'année dernière. AOL utilise un outil appelé Sonar pour le chargement à la demande basé sur la position de défilement. Vérifiez le code pour les détails de la façon dont il compare scrollTop (et d'autres) au décalage de l'élément pour détecter si une partie ou la totalité de l'élément est visible.

jQuery Sonar

Dave parle de Sonar dans ces diapositives . Le sondeur commence sur la diapositive 46, tandis que la discussion générale sur la «charge à la demande» commence sur la diapositive 33.

Annika Backstrom
la source
Je me demande comment cela se compare à la charge paresseuse d'Appelsinii? Est-ce plus léger? Fonctionne-t-il sur tous les navigateurs? Je me souviens que lazyload ne fonctionne pas sur Chrome.
deathlock
8

J'ai proposé ma propre méthode de base qui semble fonctionner correctement (jusqu'à présent). Il y a probablement une douzaine de choses auxquelles certains des scripts populaires traitent et auxquelles je n'ai pas pensé.

Remarque - Cette solution est rapide et facile à mettre en œuvre, mais n'est bien sûr pas excellente pour les performances. Regardez certainement dans le nouvel Intersection Observer comme mentionné par Apoorv et expliqué par developer.google si les performances sont un problème.

Le JQuery

$(window).scroll(function() {
    $.each($('img'), function() {
        if ( $(this).attr('data-src') && $(this).offset().top < ($(window).scrollTop() + $(window).height() + 100) ) {
            var source = $(this).data('src');
            $(this).attr('src', source);
            $(this).removeAttr('data-src');
        }
    })
})

Exemple de code html

<div>
    <img src="" data-src="pathtoyour/image1.jpg">
    <img src="" data-src="pathtoyour/image2.jpg">
    <img src="" data-src="pathtoyour/image3.jpg">
</div>

Expliqué

Lorsque la page défile, chaque image de la page est cochée.

$(this).attr('data-src') - si l'image a l'attribut data-src

et à quelle distance ces images sont du bas de la fenêtre.

$(this).offset().top < ($(window).scrollTop() + $(window).height() + 100)

ajustez le + 100 à ce que vous voulez (- 100 par exemple)

var source = $(this).data('src');- obtient la valeur de data-src=aka l'url de l'image

$(this).attr('src', source); - met cette valeur dans le src=

$(this).removeAttr('data-src'); - supprime l'attribut data-src (pour que votre navigateur ne gaspille pas de ressources à jouer avec les images déjà chargées)

Ajout au code existant

Pour convertir votre html, dans un éditeur, recherchez et remplacez src="parsrc="" data-src="

Hastig Zusammenstellen
la source
parfait. bless fam 🙏
LifterCoder
5

Il y a un joli plugin de défilement infini ici

Je n'en ai jamais programmé un moi-même, mais j'imagine que c'est ainsi que cela fonctionne.

  1. Un événement est lié au défilement de la fenêtre

    $(window).scroll(myInfinteScrollFunction);
  2. La fonction appelée vérifie si le haut du défilement est supérieur à la taille de la fenêtre

    function myInfiniteScrollFunction() {  
        if($(window).scrollTop() == $(window).height())  
        makeAjaxRequest();  
    }
  3. Une requête AJAX est effectuée, spécifiant le résultat # à commencer, le nombre à saisir et tout autre paramètre nécessaire à l'extraction de données.

    $.ajax({
        type: "POST",
        url:  "myAjaxFile.php",
        data: {"resultNum": 30, "numPerPage": 50, "query": "interesting%20icons" },
        success: myInfiniteLoadFunction(msg)
    });
  4. L'ajax renvoie du contenu (probablement au format JSON) et les transmet à la fonction loadnig.

J'espère que cela a du sens.

jwegner
la source
3

Le chargement paresseux d'images en attachant un auditeur pour faire défiler les événements ou en utilisant setInterval est très peu performant car chaque appel à getBoundingClientRect () oblige le navigateur à remettre en page la page entière et introduira un jank considérable sur votre site Web.

Utilisez Lozad.js (seulement 569 octets sans dépendances), qui utilise IntersectionObserver pour charger les images de manière performante.

Apoorv Saxena
la source
Polyfill peut être ajouté dynamiquement au cas où la prise en charge du navigateur n'est pas disponible
Apoorv Saxena
La prise en charge des navigateurs est bien meilleure de nos jours - puis-je utiliser
Hastig Zusammenstellen
1

Le couteau suisse du chargement paresseux d'image est ImageLoader de YUI .

Parce qu'il y a plus à ce problème que de simplement regarder la position de défilement.

Arnaud Meuret
la source
0

Ce lien fonctionne pour moi démo

1.Chargez le plugin jQuery loadScroll après la bibliothèque jQuery, mais avant la balise body de fermeture.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script><script src="jQuery.loadScroll.js"></script>

2.Ajoutez les images dans votre page Web à l'aide de l'attribut Html5 data-src. Vous pouvez également insérer des espaces réservés à l'aide de l'attribut src normal d'img.

<img data-src="1.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="2.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="3.jpg" src="Placeholder.jpg" alt="Image Alt">

3.Appelez le plugin sur les balises img et spécifiez la durée de l'effet fadeIn lorsque vos images sont visibles

$('img').loadScroll(500); // in ms
vebs
la source
0

Im utilisant jQuery Lazy . Il m'a fallu environ 10 minutes pour tester et une heure ou deux pour ajouter à la plupart des liens d'image sur l'un de mes sites Web ( CollegeCarePackages.com ). Je n'ai AUCUNE relation (aucune / zéro) de quelque sorte que ce soit avec le développeur, mais cela m'a fait gagner beaucoup de temps et a essentiellement contribué à améliorer notre taux de rebond pour les utilisateurs mobiles et je l'apprécie.

Cliff Ribaudo
la source