13 octobre 2020

Le Défilement

L’événement scroll permet de réagir sur le défilement d’une page ou d’un élément. Il y a pas mal de bonnes choses que nous pouvons faire ici.

Par exemple:

  • Montrer/cacher des contrôles additionnelles ou information selon la ou se trouve l’utilisateur sur le document.
  • Charger plus de données lorsque l’utilisateur défile vers le bas jusqu’à la fin de la page.

Voici une petite fonction pour montrer la position actuelle du défilement:

window.addEventListener('scroll', function() {
  document.getElementById('showScroll').innerHTML = window.pageYOffset + 'px';
});

en action:

Current scroll = Faites défiler la fenêtre

L’évènement scroll fonctionne aussi bien avec window qu’avec les éléments defilables.

Empêcher le défilement

Comment fait-on quelque chose de non-scrollable ?

Nous ne pouvons pas empêcher le défilement en utilisant event.preventDefault() dans l’écouteur onscroll, car il se déclenche après le défilement qui est déjà passé.

Mais nous pouvons empêcher le défilement avec event.preventDefault() sur un événement qui provoque le défilement, par exemple, l’événement keydown pour pageUp et pageDown.

Si nous ajoutons un gestionnaire d’évènement a ces évènements et à event.preventDefault() , alors le défilement ne pas se déclencher.

Il existe de nombreuses façons d’initialiser un défilement. Il est donc plus fiable d’utiliser la propriété CSS overflow.

Voici quelques taches que vous pouvez résoudre oubien regarder afin de voir une application de l’évènement onscroll.

Exercices

importance: 5

Créez une page sans fin. Lorsqu’un visiteur la défile vers la fin, elle y appose automatiquement au texte l’heure et la date en temps réelle (de sorte à ce que le visiteur puisse défiler d’avantage la page).

Comme ceci:

S’il vous plait veuillez noter deux importants aspects du défilement:

  1. Le défilement est “élastique”. Nous pouvons défiler un peu au-delà du début ou la fin du document avec certains navigateurs /appareils (l’espace vide en bas est montrée, et ensuite le document va automatiquement “retourner” à la normale).
  2. Le défilement est imprécis. Quand nous défilons vers la fin de la page, alors nous pouvons être en réalité entre 0-50px de la fin réelle document.

donc, “le défilement vers la fin” doit signifier que le visiteur n’est pas à plus de 100px de la fin du document.

P.S. En réalité nous pourrions vouloir montrer " plus de messages" ou " plus de bonnes choses".

Open a sandbox for the task.

L’essence de la solution est une fonction qui ajoute plus de dates à la page (ou charge plus de chose en réalité) alors que nous sommes en fin de page.

Nous pouvons l’appeler immédiatement et y ajouter un contrôleur d’évènement avec window.onscroll.

La question cruciale est: " Comment détectons nous que la page est défilée vers le bas?"

Utilisons les coordonnées relatives de window: window-relative.

Le document est représenté (et contenu) dans la balise <html>, qui est document.documentElement.

Nous pouvons obtenir les coordonnées relatives à la fenêtre du document en entier avec document.documentElement.getBoundingClientRect(), la propriété bottom sera la coordonnée relative à la fenêtre de la fin du document.

Par exemple, si la hauteur totale du document HTML est de 2000px, alors :

// Lorsqu'on est en haut de la page

// window-relative top = 0
document.documentElement.getBoundingClientRect().top = 0

// window-relative en bas de page = 2000
// le document est long, alors c'est probablement bien au-delà des limites inferieures de la fenêtre
document.documentElement.getBoundingClientRect().bottom = 2000

Si nous défilonsla page de 500px vers le bas, alors:

// document top is above the window 500px
document.documentElement.getBoundingClientRect().top = -500
// le bas du document est  500px plus proche
document.documentElement.getBoundingClientRect().bottom = 1500

Lorsque nous défilons jusque vers la fin, en assumant que la hauteur de la fenêtre est de 600px:

// La limite supérieure du document est au-dessus de la fenêtre à 1400px
document.documentElement.getBoundingClientRect().top = -1400
// Le bas du document est au bas de la fenêtre à 600px
document.documentElement.getBoundingClientRect().bottom = 600

Veuillez noter que le bottom ne peut être 0, parce qu’elle n’atteint jamais le haut de la fenêtre. La limite la plus basse de coordonées bottom est la hauteur de la fenêtre (nous avons supposé que ce soit 600), nous ne pouvons plus la défiler vers le haut.

Nous pouvons obtenir la hauteur de la fenêtre comme document.documentElement.clientHeight.

Pour notre tâche, nous devons savoir quand la fin du document n’est pas plus éloigné de 100px (c’est-à-dire 600-700px si la hauteur est 600).

Donc voici la fonction:

function populate() {
  while(true) {
    // la fin du document
    let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;

    // si l'utilisateur n'a pas fait défiler suffisamment loin (> 100px jusqu'à la fin)
    if (windowRelativeBottom > document.documentElement.clientHeight + 100) break;

    // ajoutons plus de données
    document.body.insertAdjacentHTML("beforeend", `<p>Date: ${new Date()}</p>`);
  }
}

Ouvrez la solution dans une sandbox.

importance: 5

Créer un bouton nomme “to the top” pour aider à effectuer un défilement de page.

Cela doit être ainsi:

  • Tandis que la page n’est pas défilée vers le bas pour au moins une hauteur égale a la fenêtre – être invisible.
  • Quand la page est défilée vers le bas au-delà de la hauteur de la fenêtre – il doit apparaitre une flèche pointant “vers le haut” au coin gauche supérieur. Si la page est défilée dans l’autre sens, elle disparait.
  • Lorsqu’on clique sur la flèche, la page défile vers le haut.

Comme ceci (coin supérieur gauche, faites défiler pour voir) :

Open a sandbox for the task.

importance: 4

Disons que nous avons un client lent et nous voulons sauvegarder leur trafique de donnée mobile.

A cet effet, nous décidons de ne pas montrer les images immédiatement, mais plutôt les remplacer avec des conteneurs d’images, comme ainsi:

<img src="placeholder.svg" width="128" height="128" data-src="real.jpg">

Donc, initialement toutes les images sont des placeholder.svg. Lorsque la page défile a la position ou l’utilisateur peut voir l’image – nous changeons src à celui qui est dans data-src, ainsi l’image va être chargée.

Voici un exemple dans un iframe:

Défilez-le pour voir les images s’afficher à la “demande”.

Les requis:

  • Quand la page est chargée, ces images qui sont à l’écran doivent s’afficher immédiatement, avant tout défilement.
  • Certaines images peuvent être régulières, sans la propriété data-src. Le code ne doit pas les toucher.
  • Une fois une image est chargée, elle ne doit plus être rechargée lorsqu’elle est défilée en vue/hors de vue.

P.S. Si vous pouvez, trouvez une solution plus avancée qui pourrait “pré-charger” les images qui sont sur une page en bas/après la position actuelle.

P.P.S. Le défilement vertical sera seulement géré, et non pas le défilement horizontal.

Open a sandbox for the task.

Nous souhaitons également l’exécuter lors du chargement de la page, afin de détecter les images immédiatement visibles et de les charger.

Le code doit être exécuté lors du chargement du document afin qu’il ait accès à son contenu.

Ou le mettre en dessous du <body> :

// ...Le contenu de la page est en haut...

function isVisible(elem) {

  let coords = elem.getBoundingClientRect();

  let windowHeight = document.documentElement.clientHeight;


  // Le bord supérieur de l'elem est visible ?

  let topVisible = coords.top > 0 && coords.top < windowHeight;

  // bottom elem edge is visible?
  let bottomVisible = coords.bottom < windowHeight && coords.bottom > 0;

  return topVisible || bottomVisible;
}

The showVisible() function uses the visibility check, implemented by isVisible(), to load visible images:

function showVisible() {
  for (let img of document.querySelectorAll('img')) {
    let realSrc = img.dataset.src;
    if (!realSrc) continue;

    if (isVisible(img)) {
      img.src = realSrc;
      img.dataset.src = '';
    }
  }
}

showVisible();
window.onscroll = showVisible;

Pour les images visibles nous pouvons prendre img.dataset.src et l’assigner à img.src (si cela n’a pas été fait déjà).

P.S. La solution propose également une variante de isVisible qui “précharge” les images situées dans une page au-dessus / au-dessous du document en cours de défilement.

Ouvrez la solution dans une sandbox.

Carte du tutoriel

Commentaires

lire ceci avant de commenter…
  • Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
  • Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
  • Pour insérer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes -- enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)