页面滚动侦听器

763 阅读1分钟

页面滚动侦听器,就是在页面顶部,随着用户纵向滚动页面,实时反应滚动进度的元素。

实现起来也不难,核心思想是:页面滚动距离(window.pageYOffset)除以可以滚动的有效高度得到的百分比,就是滚动进度了。

HTML 结构

<div class="progress-indicator" style="width:0;"></div>

<div class="container">
    <div class="header mb-3"></div>
    <div class="content mb-3"></div>
    <div class="footer"></div>
</div>

progress-indicator 就是侦听元素了,初始宽度是 0。

.progress-indicator {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: #3273dc;
}

下面为 .container 部分添加样式。

.mb-3 {
    margin-bottom: 1rem;
}

.container {
    max-width: 480px;
    margin: 0 auto;
}

.header {
    height: 60px;
    background: skyblue;
}

.content {
    height: 2000px;
    background: lightgray;
}

.footer {
    height: 45px;
    background: #ebebeb;
}

我们要检测的滚动元素是 .content,它有 2000px 高。

下面为 window 添加监听事件 scroll,实现实时监听逻辑。

JavaScript

window.addEventListener('load', function () {
  var article = document.querySelector('.content');
  var prog = document.querySelector('.progress-indicator');

  var initialTop = getOffsetTop(article);
  var articleHeight = article.getBoundingClientRect().height;
  var viewportHeight = document.documentElement.clientHeight;

  var totalScrollHeight = (initialTop + articleHeight) - viewportHeight;

  scrollHandler();
  window.addEventListener('scroll', function () {
    scrollHandler();
  });

  function scrollHandler() {
    window.requestAnimationFrame(function () {
      var perc = Math.min(1, window.pageYOffset / totalScrollHeight);
      updateProgress(perc);
    });

    function updateProgress(perc) {
      prog.style.width = perc * 100 + '%';
    }
  }

  // Util Tool
  function getOffsetTop(elem) {
    var top = 0;

    while (elem.offsetParent) {
      top += elem.offsetTop;
      elem = elem.offsetParent;
    }

    return top;
  }
});

(完)