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

发布于 2024-09-26 18:59:59 字数 165 浏览 2 评论 0 原文

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

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

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

I'm making a pagination system (sort of like Facebook) where the content loads when the user scrolls to the bottom. I imagine the best way to do that is to find when the user is at the bottom of the page and run an Ajax query to load more posts.

The only problem is I don't know how to check if the user has scrolled to the bottom of the page. Any ideas?

I'm using jQuery, so feel free to provide answers that use it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

独行侠 2024-10-03 18:59:59

window.scroll() 事件>,像这样:

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

你可以在这里测试,这需要窗口的顶部滚动,那么如何它向下滚动,添加可见窗口的高度并检查它是否等于整体内容(文档)的高度。如果您想检查用户是否接近底部,则看起来像这样:

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

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

Use the .scroll() event on window, like this:

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

You can test it here, this takes the top scroll of the window, so how much it's scrolled down, adds the height of the visible window and checks if that equals the height of the overall content (document). If you wanted to instead check if the user is near the bottom, it'd look something like this:

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

You can test that version here, just adjust that 100 to whatever pixel from the bottom you want to trigger on.

疧_╮線 2024-10-03 18:59:59

TL;博士;

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

概念

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

换句话说,当这种等价性成立时,我们就会“滚动”::

scrollHeight - scrollTop - clientHeight === 0

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

防止舍入错误

提到 但是,其中一些属性是四舍五入的< /a>,这意味着在 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,但无需将内容“包装”在另一个元素中,直接在元素中添加文本会使元素溢出。

去抖动、延迟和节流

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

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

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

大多数时候,不做这三件事中的任何一件都可以很好地工作,因为只是看看我们是否完全滚动是相对便宜的。

TL;DR;

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

Concept

At its core, "having scrolled to the bottom" refers to the moment when the scrollable area (scrollHeight) minus the distance of the visible content from the top (scrollTop) equals the height of the visible content (clientHeight).

Differently put, we are "scrolled" when this equivalence is true::

scrollHeight - scrollTop - clientHeight === 0

Diagram showing arrows and boxes for the scrollable area, client visible height and distance from the top in a graphical browser.

Preventing Rounding Error

As mentioned however, some of these properties are rounded, which means that the equality can fail in cases where scrollTop would have a decimal component or when the rounded values align poorly.

It is possible to mitigate that problem by comparing the absolute difference to a tolerable threshold:

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

A snippet that prevents rouding error could look like this:

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>

Note that I've added a div that is too big for its container to force the scrolling but there's no need to "wrap" the content in another element, text directly in an element would make the element overflow.

Debouncing, Delaying and Throttling

The more I understand about it and the less I find it's within the scope of this answer (this Code Review question and its answer, and this linked article are of interest), but in specific cases (if the handler does expensive computation, if we tie an animation to the scroll event, if we only want to launch the event at the end of the scroll motion, or any situation that may warrants it) it can be useful to:

  • debounce (fire the handler when the first scroll happen, then prevent it from firing too fast),
  • delay (prevent the execution of the handler until the scroll event wasn't fired for a period of time. this is often called debouncing in ECMAScript context),
  • or throttle (preventing the handler to fire more than once every period of time).

Great care must be taken in choosing to do any of these things, for instance throttling the event could prevent the last scroll to fire, which could completely defeat an infinite scroller.

Not doing any of those three things works perfectly fine most of the time, as just looking if we're completely scrolled is relatively inexpensive.

无声静候 2024-10-03 18:59:59

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

要使其适用于所有浏览器,请使用 James Padolsey< /a>:

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!");
       }
   });

Nick Craver's answer works fine, spare the issue that the value of $(document).height() varies by browser.

To make it work on all browsers, use this function from 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
    );
}

in place of $(document).height(), so that the final code is:

$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });
傲鸠 2024-10-03 18:59:59

进一步的优秀接受 Nick Craver 的回答,您可以限制滚动事件,使其不会频繁触发,从而提高浏览器性能

var _throttleTimer = null;
var _throttleDelay = 100;
var $window = $(window);
var $document = $(document);

$document.ready(function () {

    $window
        .off('scroll', ScrollHandler)
        .on('scroll', ScrollHandler);

});

function ScrollHandler(e) {
    //throttle event:
    clearTimeout(_throttleTimer);
    _throttleTimer = setTimeout(function () {
        console.log('scroll');

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

    }, _throttleDelay);
}

Further to the excellent accepted answer from Nick Craver, you can throttle the scroll event so that it is not fired so frequently thus increasing browser performance:

var _throttleTimer = null;
var _throttleDelay = 100;
var $window = $(window);
var $document = $(document);

$document.ready(function () {

    $window
        .off('scroll', ScrollHandler)
        .on('scroll', ScrollHandler);

});

function ScrollHandler(e) {
    //throttle event:
    clearTimeout(_throttleTimer);
    _throttleTimer = setTimeout(function () {
        console.log('scroll');

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

    }, _throttleDelay);
}
奢望 2024-10-03 18:59:59

Nick Craver 的答案 需要稍微修改一下才能在 iOS 6 Safari Mobile 上工作,并且应该是:

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

更改 $( window).height()window.innerHeight 应该这样做,因为当地址栏隐藏时,会添加额外的 60 像素窗口的高度,但使用 $(window).height() 不会反映此更改,而使用 window.innerHeight 则会反映此更改。

注意window.innerHeight 属性还包括水平滚动条的高度(如果已呈现),与 $(window).height() 不同其中不包括水平滚动条的高度。这在 Mobile Safari 中不是问题,但可能会导致其他浏览器或未来版本的 Mobile Safari 中出现意外行为。将 == 更改为 >= 可以解决大多数常见用例的问题。

详细了解 window.innerHeight 属性 这里

Nick Craver's answer needs to be slightly modified to work on iOS 6 Safari Mobile and should be:

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

Changing $(window).height() to window.innerHeight should be done because when the address bar is hidden an additional 60 pixels are added to the window's height, but using $(window).height() does not reflect this change, while using window.innerHeight does.

Note: The window.innerHeight property also includes the horizontal scrollbar's height (if it is rendered), unlike $(window).height() which will not include the horizontal scrollbar's height. This is not a problem in Mobile Safari, but could cause unexpected behavior in other browsers or future versions of Mobile Safari. Changing == to >= could fix this for most common use cases.

Read more about the window.innerHeight property here.

北笙凉宸 2024-10-03 18:59:59

这是一个相当简单的方法

const didScrollToBottom = elm.scrollTop + elm.clientHeight == elm.scrollHeight

示例

elm.onscroll = function() {
    if(elm.scrollTop + elm.clientHeight == elm.scrollHeight) {
        // User has scrolled to the bottom of the element
    }
}

其中 elm 是从 ie 检索的元素document.getElementById

Here's a fairly simple approach

const didScrollToBottom = elm.scrollTop + elm.clientHeight == elm.scrollHeight

Example

elm.onscroll = function() {
    if(elm.scrollTop + elm.clientHeight == elm.scrollHeight) {
        // User has scrolled to the bottom of the element
    }
}

Where elm is an element retrieved from i.e document.getElementById.

迷途知返 2024-10-03 18:59:59

请检查此答案

 window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
       console.log("bottom");
    }
};

您可以执行 footerHeight - document.body.offsetHeight 来查看您是否靠近页脚或到达页脚。

Please check this answer.

 window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
       console.log("bottom");
    }
};

You can do footerHeight - document.body.offsetHeight to see if you are near the footer or reached the footer.

独自唱情﹋歌 2024-10-03 18:59:59

这是一段可以帮助您调试代码的代码。我测试了上面的答案,发现它们有问题。我已在 Chrome、Internet Explorer、Firefox、iPad (Safari)。我没有安装任何其他解决方案来测试...

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var winElement = $(window)[0];

         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
            alert('bottom');
         }
      });
   });
</script>

可能有一个更简单的解决方案,但我停在了它起作用的地方

如果您仍然遇到问题对于一些流氓浏览器,这里有一些代码可以帮助您调试:

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var details = "";
         details += '<b>Document</b><br />';
         details += 'clientHeight:' + docElement.clientHeight + '<br />';
         details += 'clientTop:' + docElement.clientTop + '<br />';
         details += 'offsetHeight:' + docElement.offsetHeight + '<br />';
         details += 'offsetParent:' + (docElement.offsetParent == null) + '<br />';
         details += 'scrollHeight:' + docElement.scrollHeight + '<br />';
         details += 'scrollTop:' + docElement.scrollTop + '<br />';

         var winElement = $(window)[0];
         details += '<b>Window</b><br />';
         details += 'innerHeight:' + winElement.innerHeight + '<br />';
         details += 'outerHeight:' + winElement.outerHeight + '<br />';
         details += 'pageYOffset:' + winElement.pageYOffset + '<br />';
         details += 'screenTop:' + winElement.screenTop + '<br />';
         details += 'screenY:' + winElement.screenY + '<br />';
         details += 'scrollY:' + winElement.scrollY + '<br />';

         details += '<b>End of page</b><br />';
         details += 'Test:' + (docElement.scrollHeight - winElement.innerHeight) + '=' + winElement.pageYOffset + '<br />';
         details += 'End of Page? ';
         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
             details += 'YES';
         } else {
             details += 'NO';
         }

         $('#test').html(details);
      });
   });
</script>
<div id="test" style="position: fixed; left:0; top: 0; z-index: 9999; background-color: #FFFFFF;">

Here is a piece of code that will help you debug your code. I tested the above answers and found them to be buggy. I have tested the following on Chrome, Internet Explorer, Firefox, iPad (Safari). I don't have any others installed to test...

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var winElement = $(window)[0];

         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
            alert('bottom');
         }
      });
   });
</script>

There may be a simpler solution, but I stopped at the point at which it worked

If you are still having problems with some rogue browser, here is some code to help you debug:

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var details = "";
         details += '<b>Document</b><br />';
         details += 'clientHeight:' + docElement.clientHeight + '<br />';
         details += 'clientTop:' + docElement.clientTop + '<br />';
         details += 'offsetHeight:' + docElement.offsetHeight + '<br />';
         details += 'offsetParent:' + (docElement.offsetParent == null) + '<br />';
         details += 'scrollHeight:' + docElement.scrollHeight + '<br />';
         details += 'scrollTop:' + docElement.scrollTop + '<br />';

         var winElement = $(window)[0];
         details += '<b>Window</b><br />';
         details += 'innerHeight:' + winElement.innerHeight + '<br />';
         details += 'outerHeight:' + winElement.outerHeight + '<br />';
         details += 'pageYOffset:' + winElement.pageYOffset + '<br />';
         details += 'screenTop:' + winElement.screenTop + '<br />';
         details += 'screenY:' + winElement.screenY + '<br />';
         details += 'scrollY:' + winElement.scrollY + '<br />';

         details += '<b>End of page</b><br />';
         details += 'Test:' + (docElement.scrollHeight - winElement.innerHeight) + '=' + winElement.pageYOffset + '<br />';
         details += 'End of Page? ';
         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
             details += 'YES';
         } else {
             details += 'NO';
         }

         $('#test').html(details);
      });
   });
</script>
<div id="test" style="position: fixed; left:0; top: 0; z-index: 9999; background-color: #FFFFFF;">
风筝在阴天搁浅。 2024-10-03 18:59:59
var elemScrolPosition = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

它计算滚动条到元素底部的距离。
如果滚动条到达底部,则等于 0。

var elemScrolPosition = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

It calculates distance scroll bar to bottom of element.
Equal 0, if scroll bar has reached bottom.

疯了 2024-10-03 18:59:59

这是一个普通的 JavaScript 解决方案,使用 ES6debounce:

document.addEventListener('scroll', debounce(() => {
  if(document.documentElement.scrollHeight === window.pageYOffset + window.innerHeight) {
    // Do something
  }
}, 500))

function debounce(e,t=300){let u;return(...i)=>{clearTimeout(u),u=setTimeout(()=>{e.apply(this,i)},t)}}

演示: https:// jsbin.com/jicikaruta/1/edit?js,output

参考文献:

Here is a vanilla JavaScript solution that uses ES6 and debounce:

document.addEventListener('scroll', debounce(() => {
  if(document.documentElement.scrollHeight === window.pageYOffset + window.innerHeight) {
    // Do something
  }
}, 500))

function debounce(e,t=300){let u;return(...i)=>{clearTimeout(u),u=setTimeout(()=>{e.apply(this,i)},t)}}

Demo: https://jsbin.com/jicikaruta/1/edit?js,output

References:

云仙小弟 2024-10-03 18:59:59

这是我的两分

$('#container_element').scroll(function() {
    console.log($(this).scrollTop() + ' + ' + $(this).height() + ' = ' + ($(this).scrollTop() + $(this).height()) + ' _ ' + $(this)[0].scrollHeight);
    if($(this).scrollTop() + $(this).height() == $(this)[0].scrollHeight) {
        console.log('bottom found');
    }
});

This is my two cents:

$('#container_element').scroll(function() {
    console.log($(this).scrollTop() + ' + ' + $(this).height() + ' = ' + ($(this).scrollTop() + $(this).height()) + ' _ ' + $(this)[0].scrollHeight);
    if($(this).scrollTop() + $(this).height() == $(this)[0].scrollHeight) {
        console.log('bottom found');
    }
});
别再吹冷风 2024-10-03 18:59:59

使用 Intersection Observer 是最便宜的检查工具如果最后一个元素在视口上可见(这意味着用户已滚动到底部)。它还通过 polyfill

var observer = new IntersectionObserver(function(entries){
   if(entries[0].isIntersecting === true)
      console.log("Scrolled to the bottom");
   else
      console.log("Not on the bottom");
}, {
   root:document.querySelector('#scrollContainer'),
   threshold:1 // Trigger only when whole element was visible
});

observer.observe(document.querySelector('#scrollContainer').lastElementChild);
#scrollContainer{
  height: 100px;
  overflow: hidden scroll;
}
<div id="scrollContainer">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
  <div>Item 7</div>
  <div>Item 8</div>
  <div>Item 9</div>
  <div>Item 10</div>
</div>

Instead of listening to the scroll event, using Intersection Observer is the inexpensive one for checking if the last element was visible on the viewport (that means the user has scrolled to the bottom). It also supported for Internet Explorer 7 with the polyfill.

var observer = new IntersectionObserver(function(entries){
   if(entries[0].isIntersecting === true)
      console.log("Scrolled to the bottom");
   else
      console.log("Not on the bottom");
}, {
   root:document.querySelector('#scrollContainer'),
   threshold:1 // Trigger only when whole element was visible
});

observer.observe(document.querySelector('#scrollContainer').lastElementChild);
#scrollContainer{
  height: 100px;
  overflow: hidden scroll;
}
<div id="scrollContainer">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
  <div>Item 7</div>
  <div>Item 8</div>
  <div>Item 9</div>
  <div>Item 10</div>
</div>

澜川若宁 2024-10-03 18:59:59

我的纯js解决方案:

let el=document.getElementById('el');
el.addEventListener('scroll', function(e) {
    if (this.scrollHeight - this.scrollTop - this.clientHeight<=0) {
        alert('Bottom');
    }
});
#el{
  width:400px;
  height:100px;
  overflow-y:scroll;
}
<div id="el">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>

My solution in plain js:

let el=document.getElementById('el');
el.addEventListener('scroll', function(e) {
    if (this.scrollHeight - this.scrollTop - this.clientHeight<=0) {
        alert('Bottom');
    }
});
#el{
  width:400px;
  height:100px;
  overflow-y:scroll;
}
<div id="el">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>

樱&纷飞 2024-10-03 18:59:59

尼克回答说很好,但是您将拥有在滚动时重复自身的功能,或者如果用户缩放了窗口则根本无法工作。我想出了一个简单的解决办法,只需 math.round 第一个高度,它的工作原理就像假设的那样。

    if (Math.round($(window).scrollTop()) + $(window).innerHeight() == $(document).height()){
    loadPagination();
    $(".go-up").css("display","block").show("slow");
}

Nick answers its fine but you will have functions which repeats itsself while scrolling or will not work at all if user has the window zoomed. I came up with an easy fix just math.round the first height and it works just as assumed.

    if (Math.round($(window).scrollTop()) + $(window).innerHeight() == $(document).height()){
    loadPagination();
    $(".go-up").css("display","block").show("slow");
}
软的没边 2024-10-03 18:59:59

我用纯 JavaScript 以一种非常简单的方式完成了这一点:

function onScroll() {
    if (window.pageYOffset + window.innerHeight >= document.documentElement.scrollHeight - 50) {
        Console.log('Reached bottom')
    }
}
window.addEventListener("scroll", onScroll);

I have done this in a very easy way with pure JavaScript:

function onScroll() {
    if (window.pageYOffset + window.innerHeight >= document.documentElement.scrollHeight - 50) {
        Console.log('Reached bottom')
    }
}
window.addEventListener("scroll", onScroll);
笛声青案梦长安 2024-10-03 18:59:59

如果有人想要一个普通的 JavaScript 解决方案,并且需要检测用户何时滚动到

的底部,我设法使用这些代码行来实现它

window.addEventListener("scroll", () => {
    var offset = element.getBoundingClientRect().top - element.offsetParent.getBoundingClientRect().top;
    const top = window.pageYOffset + window.innerHeight - offset;

    if (top === element.scrollHeight) {
        console.log("bottom");
    }
}, { passive: false });

In case someone wants a vanilla JavaScript solution and needs to detect when a user has scrolled to the bottom of a <div> I managed to implement it by using these lines of code

window.addEventListener("scroll", () => {
    var offset = element.getBoundingClientRect().top - element.offsetParent.getBoundingClientRect().top;
    const top = window.pageYOffset + window.innerHeight - offset;

    if (top === element.scrollHeight) {
        console.log("bottom");
    }
}, { passive: false });
淡水深流 2024-10-03 18:59:59

我使用此测试来检测滚动到达底部:

event.target.scrollTop === event.target.scrollHeight - event.target.offsetHeight

I used this test to detect the scroll reached the bottom:

event.target.scrollTop === event.target.scrollHeight - event.target.offsetHeight

亽野灬性zι浪 2024-10-03 18:59:59

Safari 可以滚动到页面底部,这导致我们的应用程序出现错误。使用 >= 而不是 === 解决此问题。

container.scrollTop >= container.scrollHeight - container.clientHeight

Safari can scroll past the bottom of the page which was causing a bug in our application. Solve this using >= instead of ===.

container.scrollTop >= container.scrollHeight - container.clientHeight
╰◇生如夏花灿烂 2024-10-03 18:59:59

所有这些解决方案在 Firefox 和 Chrome 上都不适合我,因此我使用 Miles O'Keefe 和 < a href="https://stackoverflow.com/a/3333336/3406616">meder omuraliev 像这样:

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

function getWindowSize()
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return [myWidth, myHeight];
}

$(window).scroll(function()
{
    if($(window).scrollTop() + getWindowSize()[1] == getDocHeight())
    {
        alert("bottom!");
    }
});

All these solutions doesn't work for me on Firefox and Chrome, so I use custom functions from Miles O'Keefe and meder omuraliev like this:

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

function getWindowSize()
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return [myWidth, myHeight];
}

$(window).scroll(function()
{
    if($(window).scrollTop() + getWindowSize()[1] == getDocHeight())
    {
        alert("bottom!");
    }
});
嗼ふ静 2024-10-03 18:59:59

您可以尝试以下代码,

$("#dashboard-scroll").scroll(function(){
    var ele = document.getElementById('dashboard-scroll');
    if(ele.scrollHeight - ele.scrollTop === ele.clientHeight){
       console.log('at the bottom of the scroll');
    }
});

You can try the following code,

$("#dashboard-scroll").scroll(function(){
    var ele = document.getElementById('dashboard-scroll');
    if(ele.scrollHeight - ele.scrollTop === ele.clientHeight){
       console.log('at the bottom of the scroll');
    }
});
梦忆晨望 2024-10-03 18:59:59

如果滚动到底部,请尝试此匹配条件

if ($(this)[0].scrollHeight - $(this).scrollTop() == 
    $(this).outerHeight()) {

    //code for your custom logic

}

Try this for match condition if scroll to bottom end

if ($(this)[0].scrollHeight - $(this).scrollTop() == 
    $(this).outerHeight()) {

    //code for your custom logic

}
沒落の蓅哖 2024-10-03 18:59:59

当检查可滚动元素(即不是窗口)时,这会给出准确的结果:

// `element` is a native JS HTMLElement
if ( element.scrollTop == (element.scrollHeight - element.offsetHeight) )
    // Element scrolled to bottom

offsetHeight应该给出实际可见 元素的高度(包括内边距、边距、滚动条),scrollHeight 是元素的整个高度,包括不可见(溢出)地区。

jQuery.outerHeight() 应该给出与 JS 的 .offsetHeight 类似的结果 --
MDN 中关于 offsetHeight 的文档并不清楚其跨浏览器支持。为了涵盖更多选项,这更加完整:

var offsetHeight = ( container.offsetHeight ? container.offsetHeight : $(container).outerHeight() );
if  ( container.scrollTop == (container.scrollHeight - offsetHeight) ) {
   // scrolled to bottom
}

This gives accurate results, when checking on a scrollable element (i.e. not window):

// `element` is a native JS HTMLElement
if ( element.scrollTop == (element.scrollHeight - element.offsetHeight) )
    // Element scrolled to bottom

offsetHeight should give the actual visible height of an element (including padding, margin, and scrollbars), and scrollHeight is the entire height of an element including invisible (overflowed) areas.

jQuery's .outerHeight() should give similar result to JS's .offsetHeight --
the documentation in MDN for offsetHeight is unclear about its cross-browser support. To cover more options, this is more complete:

var offsetHeight = ( container.offsetHeight ? container.offsetHeight : $(container).outerHeight() );
if  ( container.scrollTop == (container.scrollHeight - offsetHeight) ) {
   // scrolled to bottom
}

深爱不及久伴 2024-10-03 18:59:59

这是我的两分钱,因为接受的答案对我不起作用。

var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;

Here's my two cents as the accepted answer didn't work for me.

var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;
平定天下 2024-10-03 18:59:59

(2021)
这里的很多答案都涉及对 element 的引用,但如果您只关心整个页面,只需使用:

function isBottom() {
  const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
  const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
  return distanceFromBottom < 20; // adjust the number 20 yourself
}

(2021)
Lots of answers here involve a ref to an element, but if you only care about the whole page, just use:

function isBottom() {
  const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
  const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
  return distanceFromBottom < 20; // adjust the number 20 yourself
}
呆头 2024-10-03 18:59:59

我使用了 ddanone 的回答并添加了 Ajax 调用。

$('#mydiv').on('scroll', function() {
    function infiniScroll(this);
});

function infiniScroll(mydiv) {
    console.log($(mydiv).scrollTop() + ' + ' + $(mydiv).height() + ' = ' + ($(mydiv).scrollTop() + $(mydiv).height()) + ' _ ' + $(mydiv)[0].scrollHeight);

    if($(mydiv).scrollTop() + $(mydiv).height() == $(mydiv)[0].scrollHeight) {
        console.log('bottom found');
        if(!$.active){ // If there isn't any Ajax call active
                       // (the last Ajax call waiting for results)
                       // do my Ajax call again
            myAjaxCall();
        }
    }
}

I used ddanone's answer and added an Ajax call.

$('#mydiv').on('scroll', function() {
    function infiniScroll(this);
});

function infiniScroll(mydiv) {
    console.log($(mydiv).scrollTop() + ' + ' + $(mydiv).height() + ' = ' + ($(mydiv).scrollTop() + $(mydiv).height()) + ' _ ' + $(mydiv)[0].scrollHeight);

    if($(mydiv).scrollTop() + $(mydiv).height() == $(mydiv)[0].scrollHeight) {
        console.log('bottom found');
        if(!$.active){ // If there isn't any Ajax call active
                       // (the last Ajax call waiting for results)
                       // do my Ajax call again
            myAjaxCall();
        }
    }
}
人生戏 2024-10-03 18:59:59

如果您调用 $(window).height(),Google Chrome 就会给出页面的完整高度。

相反,使用 window.innerHeight 来检索窗口的高度。

必要的检查应该是:

if($(window).scrollTop() + window.innerHeight > $(document).height() - 50) {
    console.log("reached bottom!");
}

Google Chrome gives the full height of the page if you call $(window).height().

Instead, use window.innerHeight to retrieve the height of your window.

The necessary check should be:

if($(window).scrollTop() + window.innerHeight > $(document).height() - 50) {
    console.log("reached bottom!");
}
若无相欠,怎会相见 2024-10-03 18:59:59

许多其他解决方案对我不起作用,因为滚动到底部时,我的 div 触发了警报两次,向上移动时也触发了几个像素,因此解决方案是:

$('#your-div').on('resize scroll', function()
{
    if ($(this).scrollTop() +
        $(this).innerHeight() >=
        $(this)[0].scrollHeight + 10)
    {
        alert('reached bottom!');
    }
});

Many other solutions don't work for me, because on scroll to the bottom, my div was triggering the alert two times and when moving up it was also triggering up to a few pixels so the solution is:

$('#your-div').on('resize scroll', function()
{
    if ($(this).scrollTop() +
        $(this).innerHeight() >=
        $(this)[0].scrollHeight + 10)
    {
        alert('reached bottom!');
    }
});
ぶ宁プ宁ぶ 2024-10-03 18:59:59

尝试了所有答案,但没有一个对我有用。但是,一些答案没有考虑缩放问题,当用户放大或缩小时,计算可能无法按预期进行。

以下是您需要在 ReactJS 中执行的操作:

假设我们有一个物理屏幕分辨率为 1920x1080 像素且设备像素比为 2 的设备。这意味着设备的虚拟屏幕分辨率为 960x540 CSS 像素(由于设备像素比为 2,因此 CSS 像素数是物理像素数的一半)。

现在假设我们要计算视口的物理像素高度。我们可以通过将 CSS 像素中的视口高度(可以使用 document.documentElement.clientHeight 获得)乘以设备像素比(可以使用 window.devicePixelRatio 获得)来实现此目的)。

因此,如果以 CSS 像素为单位的视口高度为 540,则:

const clientHeight = document.documentElement.clientHeight * window.devicePixelRatio;

const viewportHeightInPixels = clientHeight; // since devicePixelRatio is 2 in this example
console.log(viewportHeightInPixels); // Output: 1080

在本示例中,viewportHeightInPixels 将等于 1080,因为我们已将以 CSS 像素为单位的视口高度(即 540)乘以设备像素比 (<是 2)。

这告诉我们,视口的物理像素高度为1080,这与设备的物理屏幕分辨率相同。

下面是一个示例代码片段,它使用此计算来检查用户是否已滚动到页面底部:

import { useEffect } from "react";

export default function CheckUserScroll(onBottomReached) {
  useEffect(() => {
    function handleScroll() {
      console.log('handleScroll')
      const scrollTop = document.documentElement.scrollTop;
      const scrollHeight = document.documentElement.scrollHeight;
      // Calculates the height of the client viewport, adjusted for the device's pixel ratio
      const clientHeight = document.documentElement.clientHeight * window.devicePixelRatio;
      if (scrollTop + clientHeight >= scrollHeight) {
        onBottomReached();
      }
    }
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [onBottomReached]);
}

以下是如何在 JSX 代码中使用它:

import React from 'react';
import CheckUserScroll from './CheckUserScroll';

export default function Test() {
  function handleBottomReached() {
    console.log('bottom reached!');
    // do something else here
  }

  return (
    <div>
      <CheckUserScroll bottomReached={handleBottomReached} />
      <div style={{ height: '3000px' }}>Scroll down to trigger bottomReached function</div>
    </div>
  );
}

Trying all the answers, none of them worked for me. However, some of the answers did not take into account the issue of zooming, where the calculation may not work as expected when the user zooms in or out.

Here is what you need to do in ReactJS :

Let's say we have a device with a physical screen resolution of 1920x1080 pixels and a device pixel ratio of 2. This means that the device has a virtual screen resolution of 960x540 CSS pixels (since the device pixel ratio is 2, the number of CSS pixels is half the number of physical pixels).

Now let's say we want to calculate the height of the viewport in physical pixels. We can do this by multiplying the height of the viewport in CSS pixels (which we can get using document.documentElement.clientHeight) by the device pixel ratio (which we can get using window.devicePixelRatio).

So, if the height of the viewport in CSS pixels is 540, then:

const clientHeight = document.documentElement.clientHeight * window.devicePixelRatio;

const viewportHeightInPixels = clientHeight; // since devicePixelRatio is 2 in this example
console.log(viewportHeightInPixels); // Output: 1080

In this example, viewportHeightInPixels would be equal to 1080, since we've multiplied the viewport height in CSS pixels (which is 540) by the device pixel ratio (which is 2).

This tells us that the height of the viewport in physical pixels is 1080, which is the same as the device's physical screen resolution.

Here is an example code snippet that uses this calculation to check if the user has scrolled to the bottom of the page:

import { useEffect } from "react";

export default function CheckUserScroll(onBottomReached) {
  useEffect(() => {
    function handleScroll() {
      console.log('handleScroll')
      const scrollTop = document.documentElement.scrollTop;
      const scrollHeight = document.documentElement.scrollHeight;
      // Calculates the height of the client viewport, adjusted for the device's pixel ratio
      const clientHeight = document.documentElement.clientHeight * window.devicePixelRatio;
      if (scrollTop + clientHeight >= scrollHeight) {
        onBottomReached();
      }
    }
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [onBottomReached]);
}

Here is how you can use it in your JSX code:

import React from 'react';
import CheckUserScroll from './CheckUserScroll';

export default function Test() {
  function handleBottomReached() {
    console.log('bottom reached!');
    // do something else here
  }

  return (
    <div>
      <CheckUserScroll bottomReached={handleBottomReached} />
      <div style={{ height: '3000px' }}>Scroll down to trigger bottomReached function</div>
    </div>
  );
}
〗斷ホ乔殘χμё〖 2024-10-03 18:59:59

停止重复提醒尼克的回答

ScrollActivate();

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

To stop repeated alert of Nick's answer

ScrollActivate();

function ScrollActivate() {
    $(window).on("scroll", function () {
        if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
            $(window).off("scroll");
            alert("near bottom!");
        }
    });
}
凉城已无爱 2024-10-03 18:59:59

这是最简单的方法:

const handleScroll = () => {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight) {
   console.log('scrolled to the bottom')
}}

window.addEventListener('scroll', handleScroll)

Here is the most simple way to do it:

const handleScroll = () => {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight) {
   console.log('scrolled to the bottom')
}}

window.addEventListener('scroll', handleScroll)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文