• JS实现网站楼层导航效果


     壹 ❀ 引

    我在angularjs中使用锚点这篇文章中,踩坑并简单实现了楼层导航中点击小图标跳转到对应楼层的功能;但对于楼层导航而言,还有个重要的功能就是,随着滚动条滚动,达到某层时得同步点亮楼层导航的小图片。

    由于我前面也说了不打算使用JQ,所以想着用JS去实现它,实现并不难,主要得弄清滚动满足怎样的条件才应该点亮对应楼层,我们先看看实现效果:

     贰 ❀ 实现思路

    第一点,因为是由滚动触发的楼层判断,所以肯定离不开onscroll事件

    第二点,我们貌似要获取每个楼层顶端距离视窗顶部的距离,随着滚动条往下滚动,此距离会不断缩小,当接近到某个距离时我们判定此楼层入画,当然其它楼层都满足此判定。

    而JQ提供了一个offset().top方法能获取这个值,js中只有一个offsetTop属性,获取的是距离自己最近position属性为非static的祖先元素的距离,此距离不随滚动条滚动而缩小

    当然我们有方法模拟计算出offset().top的值,但没必要,如果你对JQ的offset().top与js的offsetTop有什么区别,以及对如何模拟出JQ的offset().top的值有兴趣,可以参照博主这篇文章 JQ的offset().top与js的offsetTop区别详解

    这里我直接引用了我之前博客得到的结论:offset().top = offsetTop - scrollTop(offsetTop 参考对象为根元素)

    为了方便理解,我们假设楼层壹顶端距离视窗顶端为0时,此时判定楼层壹入画,即楼层导航中第一个按钮应该被点亮。

    由于offset().top = offsetTop - scrollTop,此时楼层壹距离顶端已经为0,我们可以得出当楼层壹的offsetTop = scrollTop时,我们认定楼层壹入画

    而当楼层贰入画时,楼层贰的offsetTop也等于滚动条的距离,此时楼层壹自然会出画:

    那么现在我们得到了判断楼层入画的条件,如果某个楼层的offsetTop属性的值小于等于滚动条距离时(如果用等于条件过于苛刻,很难刚好滚动到这个距离点上),我们点亮对应楼层的导航logo。

    为了让效果更加自然,我们肯定不会真的让某个楼层紧贴顶部时才判定它满足条件,肯定是提前某个距离就判定满足,所以真正的条件应该是offsetTop - 100(这个数字看自己感觉) <= scrollTop

    你是否会有,楼层贰入画时楼层壹依然满足offsetTop<=scrollTop条件的疑惑?在JQ里面,我们给某个元素添加点亮class的同时,还会清除掉兄弟元素的该class。

    所以在JS里面也是如此,我们利用满足楼层的索引来控制样式,而后者满足条件的索引始终会覆盖前面的索引,所以被点亮的永远只有一个

    现在弄懂了思路,代码就好些了,下面直接贴上了实现代码:

     叁 ❀ 实现代码

    HTML部分:

    <div class="floor">
        <div style="background: #ffb6b9"></div>
        <div style="background: #fae3d9"></div>
        <div style="background: #bbded6"></div>
        <div style="background: #8ac6d1"></div>
        <div style="background: #fff1ac"></div>
    </div>
    <ul class="floorNav">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    View Code

    CSS部分:

    * {
        padding: 0;
        margin: 0;
        list-style: none;
    }
    
    .floor>div {
        height: 900px;
        line-height: 900px;
        text-align: center;
        color: #fff;
        font-size: 40px;
    }
    
    .floorNav {
        width: 40px;
        height: 200px;
        position: fixed;
        right: 0;
        top: 0;
        bottom: 0;
        margin: auto;
        background: #ddd;
    }
    
    .floorNav>li {
        height: 40px;
        line-height: 40px;
        text-align: center;
        color: #fff;
    }
    
    .active {
        background: #e4393c;
        color: #fff;
    }
    View Code

    JS部分:

    //获取楼层
    let floors = document.querySelectorAll(".floor>div");
    //获取楼层导航
    let floorNavs = document.querySelectorAll(".floorNav>li");
    //滚动监听
    window.onscroll = function () {
        //获取滚动条高度,兼容ie
        let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        //符合点亮条件的楼层索引
        let activeIndex;
        //楼层导航图标点亮控制
        floors.forEach((floor, index) => {
            //检查各楼层顶端距离视窗顶端距离,如果满足条件则修改楼层图标
            floor.offsetTop - 100 <= scrollTop ? activeIndex = index : null;
        });
        //根据索引数设置楼层样式
        floorNavs.forEach((nav, index) => {
            index === activeIndex ? nav.classList.add('active') : nav.classList.remove('active');
        });
    };
    View Code

    需要注意的是,这里我使用了js中操作classList对象的add方法与remove方法,这两个方法IE并不支持,因为我这边是不需要考虑IE的,所以就任性了。

    如果考虑兼容性,还是得模拟实现JQ的addClass方法,有兴趣可以参考博主 js实现 addClass方法,classList与className有什么区别这篇文章。

    本文只是提供了一个楼层导航的思路,实现肯定不是很好,若有更佳的做法,欢迎留言讨论,那么本文结束。

  • 相关阅读:
    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别(转)
    JSP语法
    Web开发基础(读书笔记)
    eclispe新导入的文件有个小红叉号(x)的问题
    Vue处理数据,数组更新,但视图无法得到及时更新
    VUE 利用tab切换+同路由跳转传参(check)+vant上拉加载制作订单列表(终)
    适配方案一之:利用rem和less计算制作移动端适配页面
    Git常用命令务忘
    git提交代码步骤笔记
    Vue仿淘宝订单状态的tab切换效果——(但现实中不会用此种方式进行存储数据)
  • 原文地址:https://www.cnblogs.com/echolun/p/11374592.html
Copyright © 2020-2023  润新知