web-dev-qa-db-fra.com

Comment détecter le défilement vers le bas de l'élément html

J'ai cet élément que je référence par Id:

    let infiniteScrollElement = document.getElementById('th-infinite-scroll-tracker');

J'ai besoin d'écouter lorsque le navigateur a atteint le bas de l'élément.

Comment y parvenir?

13
CommonSenseCode

Je pense que tout ce que vous voulez faire est de détecter la position du défilement.

@HostListener("window:scroll", ["$event"])
onWindowScroll() {
//In chrome and some browser scroll is given to body tag
let pos = (document.documentElement.scrollTop || document.body.scrollTop) + document.documentElement.offsetHeight;
let max = document.documentElement.scrollHeight;
// pos/max will give you the distance between scroll bottom and and bottom of screen in percentage.
 if(pos == max )   {
 //Do your action here
 }
}

N'oubliez pas non plus d'importer HostListener depuis @ angular/core.

21
YASH DAVE

Vous pouvez vérifier si l'utilisateur a défilé vers le bas ou non de la manière suivante ...

fichier Html

<div (scroll)="onScroll($event)">
    ...
    ...
</div>

fichier TypeScript

import { Component, HostListener } from '@angular/core';
    ...
    ...
@HostListener('scroll', ['$event'])
onScroll(event: any) {
    // visible height + pixel scrolled >= total height 
    if (event.target.offsetHeight + event.target.scrollTop >= event.target.scrollHeight) {
      console.log("End");
    }
}
25
Narottam Goyal

Vous pouvez le faire avec un observable qui suit l'événement de défilement de votre conteneur.

Ou vous pouvez créer un écouteur d'hôte pour votre composant qui écoute l'événement de défilement. Veuillez jeter un oeil à ceci SO question . (Je ne l'ai pas testé avec un écouteur Host mais cela devrait fonctionner.)

Ajoutez le code suivant à votre composant pour une approche observable (j'ai copié une partie du code de ce article de blog .):

  ngOnInit() {
    /*
     * Create the observable from an event, in this case, the window scroll event
     * then map each event so we can get a new value from it
     * i.e. over time, we are just dealing with a collection:
     * (map [e1, e2, e3, ...]) -> [t1, t2, t3, ...]
     */
    let tracker = document.getElementById('th-infinite-scroll-tracker');

    let windowYOffsetObservable = Observable.fromEvent(tracker, 'scroll').map(() => {
      // I don't actually care about the event, I just need to get the window offset (scroll position)
      return tracker.scrollTop;
    });

    // subscribe to our Observable so that for each new item, our callback runs
    // this is our event handler
    let scrollSubscription = windowYOffsetObservable.subscribe((scrollPos) => {
      let limit = tracker.scrollHeight - tracker.clientHeight;
      console.log(scrollPos, limit);
      if (scrollPos === limit) {
        alert('end reached');
      }
    });
  }

Mise à jour

Une autre façon et probablement la meilleure serait de créer une directive pour votre logique de suivi. Ensuite, vous pouvez facilement utiliser HostListener pour vous lier à l'événement scroll.

Code TypeScript:

import {
  Directive, HostListener
}
from '@angular/core';

@Directive({
  selector: '[scrollTracker]'
})
export class ScrollTrackerDirective {
  @HostListener('scroll', ['$event']);

  onScroll(event) {
    // do tracking
    // console.log('scrolled', event.target.scrollTop);
    // Listen to click events in the component
    let tracker = event.target;

    let limit = tracker.scrollHeight - tracker.clientHeight;
    console.log(event.target.scrollTop, limit);
    if (event.target.scrollTop === limit) {
      alert('end reached');
    }
  }

  constructor() {}
}

Balisage dans votre composant (ajoutez votre directive)

<div id="th-infinite-scroll-tracker" style="overflow-y:scroll; height: 500px;" scrollTracker>
  .... your container with scrollbar ...
</div>
14
AWolf

Je travaille littéralement sur ce point maintenant et j'ai découvert qu'il s'agit du cas d'utilisation le plus polyvalent pour " moi ".

Comme YASH DAVE mentionné, utiliser un écouteur d'hôte est votre meilleur pari pour une implémentation Angular ' onScroll'. Cependant, ' Window: Scroll ' ne fonctionnait pas pour mon cas d'utilisation ( une table injectée dans un tableau de bord) . J'ai donc eu de la chance en faisant ça


@HostListener('scroll', ['$event.target'])
 onScroll(elem){
  if(( elem.offsetHeight + elem.scrollTop) >=  elem.scrollHeight) {
     console.log("It's Lit");
  }
}'

CSS:

:Host {
     display: block;
     max-height: 700px;
     width: 100%;
     overflow-y: scroll;
     scroll-behavior: auto;
 }

Explication:

  • Fondamentalement, le "scroll" générique écoute l'événement scroll se produisant sur l'élément Host.
  • transmet la référence d'élément qui a déclenché l'événement de défilement via $ event.target à ma méthode onScroll (elem)
  • Ensuite, je prends la référence de l'élément et détermine si le offsetHeight et le ScrollTop sont supérieurs au scrollHeight (oui c'est différent alors comment les autres l'ont implémenté) reference:Implémentation de mVChr
  • Alors boom, profitez-en.
  • Remarque: Si vous avez juste besoin d'un, et je ne le soulignerai jamais assez, solution simple il suffit d'ajouter un écouteur d'événement (scroll) sur l'élément particulier

De plus, consultez This pour un aperçu de offsetHeight, clientHeight, scrollHeight.

1
Ivens Applyrs