获取页面滚动位置

220 阅读1分钟

一、核心方法与属性

获取页面滚动位置主要通过浏览器提供的DOM接口,根据场景可分为窗口滚动元素滚动两类:

二、窗口滚动位置(页面整体滚动)

1. 现代浏览器(Chrome/Firefox/Safari等)
  • window.scrollXwindow.scrollY(ES2016+):

    • 作用:获取窗口水平(scrollX)和垂直(scrollY)滚动距离(单位:像素)。
    • 示例
      console.log(`水平滚动:${window.scrollX}px,垂直滚动:${window.scrollY}px`);
      
  • window.pageXOffsetwindow.pageYOffset(兼容性更好):

    • 等价于 scrollX/scrollY,可兼容旧版浏览器(如IE9+)。
2. IE8及以下兼容方案
  • document.body.scrollLeftdocument.body.scrollTop
    • 注意:需同时检查document.documentElement(标准模式)和document.body(怪异模式):
      function getScrollPosition() {
        return {
          x: window.scrollX || window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
          y: window.scrollY || window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        };
      }
      

三、元素滚动位置(局部滚动容器)

1. element.scrollLeftelement.scrollTop
  • 作用:获取指定元素的水平/垂直滚动距离(如带有overflow: auto的div)。
  • 示例
    const scrollContainer = document.querySelector('.scroll-box');
    console.log(`容器水平滚动:${scrollContainer.scrollLeft}px`);
    
2. 与滚动相关的其他属性
  • element.scrollWidthelement.scrollHeight:元素内容的总宽度/高度(含隐藏部分)。
  • element.clientWidthelement.clientHeight:元素可视区域的宽度/高度(不含滚动条)。

四、滚动事件监听与性能优化

1. 监听滚动事件
  • window.addEventListener('scroll', callback)
    window.addEventListener('scroll', () => {
      const { x, y } = getScrollPosition();
      console.log(`滚动到:${x}, ${y}`);
      // 滚动时的逻辑(如导航栏固定、返回顶部按钮显示)
    });
    
2. 性能优化(防抖与节流)
  • 滚动事件高频触发:每秒可能触发上百次,需优化:
    • 防抖(Debounce):延迟执行,只处理最后一次滚动:
      function debounce(func, delay) {
        let timer;
        return () => {
          clearTimeout(timer);
          timer = setTimeout(func, delay);
        };
      }
      
      window.addEventListener('scroll', debounce(() => {
        // 滚动优化逻辑(如300ms内只执行一次)
      }, 300));
      
    • 节流(Throttle):控制单位时间内执行次数:
      function throttle(func, limit) {
        let inThrottle;
        return () => {
          if (!inThrottle) {
            func();
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
          }
        };
      }
      
      window.addEventListener('scroll', throttle(() => {
        // 每秒最多执行一次
      }, 1000));
      

五、应用场景与实战案例

1. 常见业务场景
  • 返回顶部按钮:当滚动距离超过一定值时显示按钮:

    window.addEventListener('scroll', () => {
      const backToTopBtn = document.getElementById('back-to-top');
      if (window.scrollY > 300) {
        backToTopBtn.style.display = 'block';
      } else {
        backToTopBtn.style.display = 'none';
      }
    });
    
  • 滚动加载(无限滚动)

    window.addEventListener('scroll', () => {
      const { scrollHeight, clientHeight, scrollTop } = document.documentElement;
      // 当滚动到距离底部100px时加载更多
      if (scrollTop + clientHeight >= scrollHeight - 100) {
        loadMoreData();
      }
    });
    
  • 导航栏样式切换:滚动时改变导航栏背景透明度:

    window.addEventListener('scroll', () => {
      const navbar = document.querySelector('.navbar');
      navbar.style.backgroundColor = `rgba(0, 0, 0, ${window.scrollY / 300})`;
    });
    

六、问题

1. 问:如何获取移动端的滚动位置?
    • 移动端浏览器与PC端一致,使用window.scrollX/YpageX/YOffset
    • 需注意:部分移动端浏览器存在“橡皮筋滚动”效果,滚动事件触发可能有延迟。
2. 问:iframe中的滚动位置如何获取?
    • 通过iframe.contentWindow访问其窗口对象:
      const iframe = document.querySelector('iframe');
      const iframeScrollX = iframe.contentWindow.scrollX;
      
    • 需注意同源策略限制(非同源iframe无法访问)。
3. 问:scrollTo() 和 scrollBy() 的区别?
    • scrollTo(x, y):滚动到指定坐标(绝对位置)。
    • scrollBy(x, y):在当前位置基础上滚动指定偏移量(相对位置)。
    • 示例
      window.scrollTo(0, 1000); // 滚动到垂直1000px处
      window.scrollBy(0, 500);  // 再向下滚动500px