实现一个简单的“返回顶部”按钮

这是我参与更文挑战的第 13 天,活动详情查看:更文挑战


虽然没啥好说的,但简单介绍一下吧

返回页面顶部的按钮允许用户快速返回页面顶部。当页面包含超过一页内容,甚至说有无限加载功能时

想象下,当这篇文章很长,你读了一半想回到文章的最开头。这个时候,一个“返回顶部”按钮就有用了。

创建“返回顶部”按钮

首先,我们先选中“返回顶部”按钮。可以先假设页面中已经有这个按钮了。

var scrollToTopBtn = document.getElementById("scrollToTopBtn")
复制代码

然后,选中整个文档。通过文档元素,可以获取到距离顶部的高度。这里将其设置为 rootElement

var rootElement = document.documentElement
复制代码

我们将在按钮上添加一个点击事件监听器。当点击按钮时执行 scrollToTop 方法:

function scrollToTop {
  // 滚动到顶部
}
scrollToTopBtn.addEventListener("click", scrollToTop)
复制代码

然后,这是滚动到顶部的方法:

function scrollToTop() {
  // 滚动到顶部
  rootElement.scrollTo({
    top: 0,
    behavior: "smooth" //动画效果
  })
}
复制代码

还记得一开始提到的“返回顶部”按钮吗?现在应该创建出来了:

<footer>
  <!-- Scroll to top button -->
  <button id="scrollToTopBtn">返回顶部</button>
</footer>
复制代码

这样我们已经达到最简单的效果了。一个简单的按钮创建成功。

但这个按钮现在是始终在界面上的,我们期望只有在需要的时候才显示这个按钮。

为了满足这个需求,有两种解决方案:

  • 使用 scroll 事件监听,当滚动到距离顶部一个合适的距离时才展现
  • 使用 IntersectionObserver ,当检测到与视口相交时展现

下面分别介绍两种方式:

检测滚动位置

可以监听 scroll 事件来控制“返回顶部”按钮的显示和隐藏

function handleScroll() {}

document.addEventListener("scroll", handleScroll)
复制代码

每次用户滚动时,handleScroll方法都会被调用。

现在我们需要滚动区间的总距离,这样通过当前距离 / 总距离 得到一个比率,根据比率确定显示隐藏。

scrollHeight 给出元素的高度,包括由于溢出而无法看到的部分。
clientHeight 以像素表示元素的内部高度,这是可见部分的高度。

因此,滚动总高度为 scrollHeightclientHeight 的差值

var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight
复制代码

通过将当前滚动的距离除以滚动总高度,可以得到一个 0-1 之间的比值。使用这个比值切换按钮显示和隐藏效果。

下面的例子中,比值设置为 0.8,表示滚动到距离顶部 80% 的位置显示或隐藏

var rootElement = document.documentElement

function handleScroll() {
  var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight
  if ((rootElement.scrollTop / scrollTotal ) > 0.80 ) {
    // 显示按钮
  } else {
    // 隐藏按钮
  }
}

document.addEventListener("scroll", handleScroll)
复制代码

可以设置合适的样式保证按钮显示隐藏。具体样式这里不表。

基于 onscroll 的监听虽然比较好理解,但监听这个事件对性能的压力较大。某些浏览器对这个事件进行了优化处理,可能会导致无法即时响应(比如移动端的 safari)。

使用 IntersectionObserver 替换 onscroll 监听

首先创建一个新的监听实例。这个监听实例允许符合条件时执行对应的回调事件

let observer = new IntersectionObserver(callback);
复制代码

设定回调事件:

function callback(entries, observer) {
  // 回调会返回一个元素数组,即便你选择监听一个元素。
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // 显示按钮
    } else {
      // 隐藏按钮
    }
  });
}
复制代码

最后,选择“返回顶部”按钮为被监听的元素

observer.observe(target);
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享