如何检测HTML元素是否滚动到底部

53

我有一个通过ID引用的元素:

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

我需要在浏览器滚动到元素底部时进行监听。

如何实现?


这个 Angular 2 模块可能会对您有所帮助 https://www.npmjs.com/package/angular2-infinite-scroll - Vinay Pandya
5个回答

97

您可以按以下方式检查用户是否滚动到底部...

Html文件

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

typescript文件

onScroll(event: any) {
    // visible height + pixel scrolled >= total height 
    if (event.target.offsetHeight + event.target.scrollTop >= event.target.scrollHeight) {
      console.log("End");
    }
}

3
必须将“===”更改为“> =”,因为当完全滚动到元素底部时,左侧方程式会变得更大。 - user2340939
5
没必要使用 HostListener,只需要 (scroll)='onScroll($event)' 就可以了。非常简单。 - Steve
不需要使用 HostListener,简单的函数也可以工作,确保同时使用 isPlatformBrowser。此外,HostListener滚动事件会不断刷新整个Angular对象,使整个应用程序变得沉重。不要使用带有HostListener的滚动事件。 - Vikas Kandari
1
对我来说,它多次触发了,这是我无法接受的。不得不使用AWolf的解决方案。 - yakya
2
我仍然在处理这个解决方案时遇到了问题,结果发现对于某些情况,scrollTop值比累加到总高度所需的值低约0.25。我的解决方案是简单地这样进行四舍五入:event.target.offsetHeight + Math.ceil(event.target.scrollTop) >= event.target.scrollHeight - mvoelcker
显示剩余4条评论

52

我认为你想要做的只是检测滚动条的位置。

@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
 }
}

还要不忘记从@angular/core引入HostListener。


它正在工作,但我想使用ID或类在特定部分上检测滚动。那么我该如何检测? - Hasmukh Ahir
1
它适用于页面滚动而不是特定的段落或div。 - K M Rifat ul alom
1
嘿@KMRifatulalom,您可以通过访问其ID来检测div的滚动。 - YASH DAVE
1
var elem = document.getElementById("speakers_list");var pos = elem.scrollTop + elem.offsetHeight;var max = elem.scrollHeight; - YASH DAVE
如何检测唯一的滚动事件 - Bhimashankar Mantur
1
使用变量prevPos(默认值:0),并将其与pos进行比较。 如果(prevPos > pos) { /* 向下滚动函数 */ } prevPos = pos; - YASH DAVE

22
您可以使用一个可观察对象来跟踪容器的滚动事件来实现此操作。
或者,您可以为组件创建一个主机监听器,以便监听滚动事件。请参考这个SO问题。(我没有使用主机监听器进行测试,但应该可以工作。)
对于可观察方法,请将以下代码添加到您的组件中(我从这篇博客文章中复制了一些代码):
  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');
      }
    });
  }

更新

另一种方法,可能是最好的方法,是为您的跟踪逻辑创建一个指令。然后,您可以轻松地使用 HostListener 来绑定滚动事件。

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() {}
}

在您的组件中使用标记(添加指令)

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

4
这是"host listener directive"的演示,你可以在这里查看该监听器的实际效果:Here - AWolf
滚动事件对我不起作用,我正在使用Angular 6,如果我将其更改为window:scroll,它就可以工作了。 - Rohit Khatri

0

试试这个,它会起作用的

@HostListener('body:scroll', ['$event'])


0

我现在正在实际进行这项工作,并发现这是最多才多艺的使用情况之一,适用于“”。

就像 YASH DAVE 提到的那样,对于 Angular 的'onScroll'实现,最好使用 Host Listener。 但是,在我的使用情况(仪表板中注入的表格)中,'Window: Scroll'没有起作用。 所以我试了这个方法


@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;
 }

解释:

  • 基本上,通用的“滚动”监听主机元素上发生的滚动事件。
  • 通过$event.target将触发滚动事件的元素引用传递给我的onScroll(elem)方法。
  • 然后,我获取元素引用并确定offsetHeight和scrollTop是否大于scrollHeight(是的,这与其他人实现的方式不同)参考:mVChr's Implementation
  • 然后就完成了。
  • 注意:如果您只需要一个(我无法强调这一点) 简单的解决方案,只需在特定元素上添加(scroll)事件侦听器即可。

此外,请查看此处以了解offsetHeight、clientHeight、scrollHeight的见解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接