开发者问题收集

检查用户是否已滚动到底部(不仅是窗口,还包括任何元素)

2010-10-09
795500

我正在制作一个分页系统(有点像 Facebook),当用户滚动到页面底部时,内容就会加载。我认为最好的方法是找到用户何时位于页面底部,然后运行 ​​Ajax 查询以加载更多帖子。

唯一的问题是我不知道如何检查用户是否已滚动到页面底部。有什么想法吗?

我正在使用 jQuery,因此请随意提供使用它的答案。

3个回答

window 上使用 .scroll() 事件,如下所示:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {
       alert("bottom!");
   }
});

您可以在此处进行测试 ,这将获取窗口的顶部滚动,因此它向下滚动了多少,添加了可见窗口的高度并检查它是否等于整体内容( document )的高度。如果您想检查用户是否 靠近 底部,它看起来会像这样:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       alert("near bottom!");
   }
});

您可以在此处测试该版本 ,只需将 100 调整为您想要触发的底部像素即可。

Nick Craver
2010-10-09

TL;DR;

Math.abs(element.scrollHeight - element.scrollTop - element.clientHeight) < 1

概念

从本质上讲,“滚动到底部”是指可滚动区域 ( scrollHeight ) 减去可见内容与顶部的距离 ( scrollTop ) 等于可见内容的高度 ( clientHeight )。

换句话说,当这个等式成立时,我们就“滚动”了::

scrollHeight - scrollTop - clientHeight === 0

在图形浏览器中显示可滚动区域、客户端可见高度和与顶部距离的箭头和框的图表。

防止舍入错误

正如 所述 ,但是, 其中一些属性是四舍五入的 ,这意味着在 scrollTop 具有小数部分或四舍五入的值对齐不佳。

可以通过将绝对差异与可容忍的阈值进行比较来缓解该问题:

Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1

防止路由错误的代码段可能如下所示:

document.getElementById('constrained-container').addEventListener('scroll', event => {
    const {scrollHeight, scrollTop, clientHeight} = event.target;

    if (Math.abs(scrollHeight - clientHeight - scrollTop) < 1) {
        console.log('scrolled');
    }
});
#constrained-container {
  height: 150px;
  overflow-y: scroll;
}

#very-long-content {
  height: 600px;
}
<div id="constrained-container">
  <div id="very-long-content">
    scroll me to the bottom
  </div>
</div>

请注意,我添加了一个 div,该 div 太大,其容器无法强制滚动,但无需将内容“包装”在另一个元素中,直接在元素中放置文本会导致元素溢出。

防抖、延迟和节流

我对此了解得越多,就越觉得它不在本答案的范围内( 代码审查 问题及其答案 ,以及 此链接文章 很有趣),但在特定情况下(如果处理程序进行昂贵的计算,如果我们将动画绑定到滚动事件,如果我们只想在滚动运动结束时启动事件,或者任何可能需要的情况),它可以很有用:

  • 去抖动(在第一次滚动发生时触发处理程序,然后防止其触发过快),
  • 延迟(阻止处理程序的执行,直到滚动事件在一段时间内没有触发。这在 ECMAScript 上下文中通常称为去抖动),
  • 或节流(防止处理程序在每个时间段内触发多次)。

在选择执行任何这些操作时必须非常小心,例如,限制事件可能会阻止最后一次滚动触发,这可能会完全击败无限滚动条。

大多数情况下,不执行这三件事中的任何一件都可以正常工作,因为仅查看我们是否完全滚动是相对便宜的。

Félix Adriyel Gagnon-Grenier
2015-12-31

Nick Craver 的答案 工作正常,省去了 $(document).height() 的值因浏览器而异的问题。

要使其在所有浏览器上运行,请使用 James Padolsey 中的以下函数:

function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

代替 $(document).height() ,以便最终代码为:

$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });
Miles O'Keefe
2012-05-29