【前端三分钟】锚点自动跟随滚动定位

简介: 【前端三分钟】锚点自动跟随滚动定位

最近看到写 “锚点自动跟随滚动定位”的方法,大都是基于JQ,或者是第三方。

所以,进行给出使用原生JS的写法。

什么都不说了,直接上代码(使用模块模式方式):

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style>
        div.section_maodian {height: 500px;width: 100%;}
        ul,li {list-style: none;}
        ul {position: fixed; right:10px;width: 100px;}
        li {height: 20px;background: burlywood;padding: 10px;cursor: pointer;}
        li.active {background-color: brown;}
        li.active {color: #fff};
    </style>
</head>
<body>
  <div class="section_maodian">秒杀专区</div>
    <div class="section_maodian">买一赠一</div>
    <div class="section_maodian">品牌齐聚</div>
    <script>
  const ScrollAnchorModule = function() {
    let scrollH = document.documentElement.scrollTop||document.body.scrollTop;
    //scroll更新
    const updateNav = (secItems,navItems) => {
      if(getScrollTop()===0)
        navon(0,navItems);
      if(getScrollTop()+getWindowHeight()===getScrollHeight())
        navon(secItems.length-1,navItems);
      else {
        secItems.forEach((item,index)=>{
          if(getScrollTop()>=item.offsetTop){
            navon(index,navItems);
          }
        });
      }
    }
    //定位
    const toScroll = (index,secItems) => {
      //计算位置
      let scrollY = secItems[index].offsetTop;
      window.scrollTo(0,scrollY);
    }
    //当前锚点
    const navon = (index,navItems) => {
      navItems.forEach((item)=>{
        item.classList = "";
      });
      navItems[index].classList = "active";
    }
    //防抖
    const debounce = (fn,wait) => {
          let timeout = null;
          return function() {
              if(timeout!==null) clearTimeout(timeout);
              timeout = setTimeout(fn,wait);
          }
      }
      //节流
    const throttle = (fn,delay) => {
          let prev = Date.now();//记录上一次触发回调的时间
          return function() {
              let context = this;//保留调用时的this上下文
              let args = arugments;//保留调用时传入的参数
              let now = Date.now();//记录本次触发回调的时间
              if(now-prev >=delay) {//判断上次触发回调的时间和本次触发回调的时间差十分小于时间间隔的阈值
                  fn.apply(context,args);//大于设定的阈值,则执行回调
                  prev = Date.now();
              }
          }
      }
      //滚动条在Y轴上的滚动距离
      const getScrollTop = () => {
        let scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0;
        if(document.body){
          bodyScrollTop = document.body.scrollTop;
        }
        if(document.documentElement){
          documentScrollTop = document.documentElement.scrollTop;
        }
        scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
        return scrollTop;
      }
      //文档的总高度
      const getScrollHeight = () =>{
        let scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0;
        if(document.body){
          bodyScrollHeight = document.body.scrollHeight;
        }
        if(document.documentElement){
          documentScrollHeight = document.documentElement.scrollHeight;
        }
        scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
        return scrollHeight;
      }
      //浏览器视口(窗口)的高度
      const getWindowHeight = () =>{
        let windowHeight = 0;
        if(document.compatMode == "CSS1Compat"){
          windowHeight = document.documentElement.clientHeight;
        }else{
          windowHeight = document.body.clientHeight;
        }
        return windowHeight;
      }
    return {//模块返回接口
      init: (options) => {
        let html = `<ul class="sideMaodian">`+options.navMenu.map((item,index)=>{
        return `<li class="nav_maodian ">${item}</li>`;
        }).join('')+`</ul>`;
        document.body.insertAdjacentHTML('afterbegin',html);
        let navItems = document.querySelectorAll(options.navClass);
        let secItems = document.querySelectorAll(options.secClass);
        let sideMaodian = document.querySelector('.sideMaodian');
        if(scrollH===0)
          navon(0,navItems);
        //利用事件冒泡机制,在点击的li元素的祖先元素ul标签上注册click事件
        sideMaodian.addEventListener('click',event=>{
          let item = event.target;
          let lists = Array.from(sideMaodian.querySelectorAll('li'));
          let index = lists.indexOf(item); //li 索引
          if(event.target.tagName.toLowerCase() === 'li'){
            navon(index,navItems);
            toScroll(index,secItems);
          }
        },false);
        //注册scroll事件
        window.addEventListener('scroll',event=>{
          event.stopPropagation();
          debounce(updateNav(secItems,navItems),1000);
        },false);
      }
    }
  }();
  var options = {
    navClass:'.nav_maodian',
    secClass:'.section_maodian',
    navMenu:['秒杀专区','买一赠一','品牌齐聚']
  }
  ScrollAnchorModule.init(options);
    </script>
</body>
</html>

参考 :

防抖与节流


相关文章
|
6月前
|
Web App开发 前端开发
【前端篇】前端实现滚动分屏效果
【前端篇】前端实现滚动分屏效果
168 0
|
6月前
|
前端开发
【前端|CSS系列第3篇】CSS盒模型、浮动及定位
【前端|CSS系列第3篇】CSS盒模型、浮动及定位
102 1
|
前端开发 测试技术
你发现一个bug,如何定位这个是前端还是后端缺陷?建议收藏
你发现一个bug,如何定位这个是前端还是后端缺陷?建议收藏
476 0
|
2月前
|
前端开发
前端基础(十三)_定位position、定位层级z-index
本文讲解了CSS中的定位机制,包括静态定位、相对定位、绝对定位和固定定位,并通过实例展示了如何使用这些定位方法调整元素位置。同时,还介绍了z-index属性的使用,解释了如何通过调整z-index值来改变定位元素的层叠顺序。
25 6
前端基础(十三)_定位position、定位层级z-index
|
2月前
|
前端开发
|
3月前
|
前端开发 容器
解锁CSS定位奥秘,从迷茫到精通,让你的网页布局“稳如老狗”,引领前端新潮流!
【8月更文挑战第23天】本文深入探讨了Web前端开发中CSS定位的三大基石:相对定位、绝对定位与固定定位。通过具体示例,展示了各种定位方式的特点及应用场景。相对定位可在不影响布局的情况下微调元素位置;绝对定位使元素完全脱离文档流,适用于精确控制位置的需求;固定定位则确保元素始终固定于浏览器窗口特定位置,不受页面滚动影响。这些技巧对于实现复杂网页布局至关重要。
51 0
|
6月前
|
前端开发 UED 开发者
【Flutter前端技术开发专栏】Flutter中的列表与滚动视图优化
【4月更文挑战第30天】Flutter开发中,优化列表和滚动视图至关重要。本文介绍了几种优化方法:1) 使用`ListView.builder`和`GridView.builder`实现懒加载;2) 复用子组件以减少实例创建;3) 利用`CustomScrollView`和`Slivers`提升滚动性能;4) 通过`NotificationListener`监听滚动事件;5) 使用`KeepAlive`保持列表项状态。掌握这些技巧能提升应用性能和用户体验。
98 1
【Flutter前端技术开发专栏】Flutter中的列表与滚动视图优化
|
6月前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
193 0
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
6月前
|
前端开发 数据处理
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
【4月更文挑战第30天】本文探讨了 Flutter 中的滚动性能优化和无限列表实现。关键点包括:1) 滚动性能直接影响用户满意度,优化可提升响应速度;2) 影响因素有布局复杂度、频繁重绘和数据处理;3) 优化措施包括懒加载、简化布局、减少不必要的重绘和高效处理数据;4) 无限列表通过监听滚动位置,动态加载新数据;5) 实现时注意加载策略、数据处理效率和内存管理。案例分析和总结强调了优化在实际开发中的重要性。
109 0
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
|
6月前
|
前端开发 JavaScript 容器
CSS属性:定位属性+案例讲解:博雅互动 前端开发入门笔记(五)
CSS属性:定位属性+案例讲解:博雅互动 前端开发入门笔记(五)
51 1