Maison >interface Web >js tutoriel >Observer le changement de position des éléments HTML à l'aide d'Intersection Observer

Observer le changement de position des éléments HTML à l'aide d'Intersection Observer

Barbara Streisand
Barbara Streisandoriginal
2025-01-12 18:28:43602parcourir

Observing position-change of HTML elements using Intersection Observer

TLDR : Utilisation d'un observateur d'intersection pour observer le changement de position des éléments sans écouter les événements de défilement ou l'interrogation continue.

Démo :

https://ajk-essential.github.io/Position-Observer/

Dépôt Github :

https://github.com/AJK-Essential/Position-Observer

Motivation:

Traditionnellement, pour observer lorsqu'un élément se déplace dans une fenêtre, nous devons nous fier à l'écoute des événements de défilement des éléments parents de l'élément HTML ou utiliser des méthodes d'interrogation continue comme l'utilisation de requestanimationframe.

Ça marche…. mais ça pourrait être mieux…

Étant donné que l'écoute des événements de défilement peut entraîner des retards de performances.
Et l'interrogation continue s'exécute toujours en arrière-plan… ce qui peut représenter une charge pour le processeur même lorsque l'élément cible ne bouge pas.

Il s'agit donc d'une approche/expérience pour voir si nous pouvons faire quelque chose avec l'Intersection Observer pour observer les changements de position des éléments html.

L'approche :

Les observateurs d'intersection sont très efficaces pour signaler si l'élément cible croise réellement un élément racine. Ils peuvent signaler des changements fractionnaires d'intersection entre l'élément cible et l'élément racine, ce qui se produit lorsque l'élément cible se déplace.

Nous avons également la possibilité de changer les dimensions de la fenêtre de capture (les rootbounds) en modifiant les marges des rootBounds.

Hmm…

L'idée :

L'idée est donc d'utiliser la fenêtre de capture pour envelopper étroitement la cible. Cela signifie que lorsque l'élément cible se déplace, il touche et croise la fenêtre de capture. Ainsi, Intersection Observer signale les infimes intersections à l'aide d'un tableau de seuil élevé (de 0 à 1 en divisions de 1/1000ème). Cela signifie que l'Intersection Observer rapporte tous les 1/1000ème de changement dans la zone d'intersection entre la cible et la racine (la fenêtre de capture)

S'il sort complètement de la fenêtre de capture (cela se produit lorsque le rapport d'intersection est de 0), alors nous modifions à nouveau les marges de la racine (la fenêtre de capture) pour qu'elles soient autour de la nouvelle position cible.

Problème de mise en œuvre auquel j'ai été confronté et comment il est résolu maintenant :

L'approche a bien fonctionné, jusqu'à ce que je rencontre des situations de défilement, où la cible était dans les dimensions de la fenêtre visuelle (à l'intérieur de l'écran) mais cachée visuellement car elle était cachée dans le contexte de défilement.

Dans ce scénario, le rapport d'intersection était toujours de 0 puisque l'intersection n'était signalée que lorsque la cible se trouvait dans la zone visuelle.

Donc, pour résoudre ce problème , l'approche que j'ai adoptée était la suivante.

Lorsque le rapport d'intersection est signalé comme étant de 0…
L'observateur d'Intersection est déconnecté puis reconnecté avec de nouveaux paramètres :
 
Les dimensions de la fenêtre de capture sont conçues pour correspondre à la totalité de l'écran (c'est-à-dire avec des marges racine égales à 0).

Et le rappel pour ce scénario est effectué dans une autre méthode afin de différencier les moments où la limite racine est la fenêtre visuelle et quand elle est juste autour de la cible.

Ainsi, lorsque l'Intersection Observer signale désormais un rapport d'intersection inférieur à 1, nous ne faisons rien. Pour chaque rapport, nous disons qu’il y a un changement de position. 

Lorsque le rapport atteint 1, cela signifie que la cible est entièrement dans la zone visuelle. Pendant ce moment, nous déconnectons à nouveau l'Intersection Observer et nous reconnectons avec une fenêtre plus fine autour de la cible avec la méthode de rappel précédente.

Ainsi, la fenêtre de capture (rootBounds) passe finalement de la fenêtre la plus fine à la fenêtre d'affichage visuelle.

Comment le mettre en œuvre ? Est-ce déjà mis en œuvre ?

Oui. J'ai implémenté la même chose qu'une classe PositionObserver dans mon dépôt Github (https://github.com/AJK-Essential/Position-Observer) . Les fichiers se trouvent dans le dossier dist. Ces fichiers peuvent être téléchargés.

Alors
la classe PositionObserver peut être importée comme ceci :

import { PositionObserver } from "./position-observer.js";

Créez ensuite une instance de ce PositionObserver comme ceci :

const positionObs = new PositionObserver(posObsCallback);

où posObsCallback est toute fonction qui accepte un paramètre d'objet de type :

 {
  x: number;
  y: number;
  target: HTMLElement | Element;
  outOfViewport: boolean;
  rootBounds: DOMRect | null;
};

Ce serait la fonction qui serait appelée comme rappel lorsque positionObserver détecte un changement de position. Les paramètres :

  • x  : représente la coordonnée x de la cible
  • y  : représente la coordonnée y de la cible
  • target : représente la cible elle-même
  • outOfViewport : représente si la cible est sortie de la zone visuelle de la fenêtre
  • rootBounds : représente la limite de l'élément racine ou de la fenêtre de capture. Utile à des fins de débogage.

Jusqu'à présent, le positionObserver a été configuré. Maintenant, pour détecter le changement de position d'un élément, nous devons l'observer comme :

positionObs.observe(target);

où la cible représente l'élément réel que nous voulons observer.
Pour arrêter d'observer le changement de position, on peut l'utiliser comme :

positionObs.disconnect()

Vous pouvez également visiter https://github.com/AJK-Essential/Position-Observer/blob/main/docs/target-scroll.html et consulter la section script pour voir un exemple d'implémentation

Limites de cet observateur :

  1. Il ne peut détecter un changement de position que lorsque la cible se déplace dans la zone visuelle.
  2. Lorsqu'il y a un changement de taille de la fenêtre ou de la cible, cela peut échouer. Donc, dans ces scénarios, mieux vaut se déconnecter puis observer à nouveau la cible.
Alors, est-ce la solution parfaite ?

Je ne sais pas. Cela a fonctionné selon mes tests. Il peut y avoir des scénarios où cela pourrait ne pas fonctionner…
Ce que je recommanderais, c'est de l'utiliser en combinaison avec l'écoute du défilement (et de l'utiliser simplement en remplacement de l'interrogation continue) car j'observe parfois qu'il manque le suivi de la cible lors du défilement dans la démo.

N'hésitez pas à utiliser et tester le code dans ce dépôt Github
(https://github.com/AJK-Essential/Position-Observer), et même modifiez-le en privé en fonction des besoins de votre projet/entreprise ou si vous avez trouvé un bug et avez également la solution pour le même.

J'espère que cela vous a été utile !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn