电梯导航---js实现

需求:

一、点击左边的小li,会滚动到右边对应的内容区(电梯导航 -> 内容区)
① 当滚动到某一位置时,就让电梯导航显示出来
② 点击电梯导航页面可以滚动到相应内容区域
③ 核心算法:因为电梯导航模块和内容区模块是一一对应的,所以对应的索引号是一样的
④ 当点击电梯导航某个小模块时,就可以拿到当前小模块的索引号
⑤ 利用document.documentElement.scrollTop 跳转页面

二、 当滚动到右边的内容区,左边的小li会添加相应的类(内容区 -> 电梯导航)
① 当点击电梯导航的某个小li,当前小li添加active类,兄弟移除类名
② 当页面滚动到内容区域某个模块,左侧电梯导航相对应的小li模块,也会添加active类,兄弟移除active类
③ 触发的事件是页面滚动,因此这个功能要写到页面滚动事件里面
⑤ 判断的条件:被卷去的头部 要在每个板块的区间内
⑥ 就利用这个区间找到相应的电梯导航小li,添加active类

注意: 在点击导航栏时有一个BUG,因为点击导航栏后页面会滚动,所以会触发(内容区 -> 电梯导航)页面滚动事件中的效果,类似抖动。

解决方法
添加一个节流阀,也叫互斥锁,增加一个isScroll判断条件,判断是不是滚动事件,如果是点击事件,就上一个锁,不要执行滚动事件里面的代码,点击事件完成之后再释放锁。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        html {
            height: 3000px;
            scroll-behavior: smooth;
        }

        .box {
            width: 900px;
            margin: 0 auto;
        }

        .floor1 {
            height: 600px;
            background-color: red;
        }

        .floor2 {
            height: 600px;
            background-color: blue;
        }

        .floor3 {
            height: 600px;
            background-color: green;
        }

        .floor4 {
            height: 600px;
            background-color: brown;
        }

        .navs {
            position: fixed;
            top: 250px;
            left: 250px;
            list-style: none;
            background-color: purple;
            opacity: 0;

        }

        .navs li {
            width: 80px;
            height: 40px;
            line-height: 40px;
            text-align: center;
        }

        .show {
            opacity: 1;
        }

        .active {
            background-color: pink;
            color: #fff;
        }
    </style>
</head>

<body>
    <!-- 
        需求:
        一、点击左边的小li,会滚动到右边对应的内容区(电梯导航 -> 内容区)
        ① 当滚动到某一位置时,就让电梯导航显示出来
        ② 点击电梯导航页面可以滚动到相应内容区域
        ③ 核心算法:因为电梯导航模块和内容区模块是一一对应的,所以对应的索引号是一样的
        ④ 当点击电梯导航某个小模块时,就可以拿到当前小模块的索引号
        ⑤ 利用document.documentElement.scrollTop 跳转页面

        二、 当滚动到右边的内容区,左边的小li会添加相应的类(内容区 -> 电梯导航)
        ① 当点击电梯导航的某个小li,当前小li添加active类,兄弟移除类名
        ② 当页面滚动到内容区域某个模块,左侧电梯导航相对应的小li模块,也会添加active类,兄弟移除active类
        ③ 触发的事件是页面滚动,因此这个功能要写到页面滚动事件里面
        ⑤ 判断的条件:被卷去的头部 要在每个板块的区间内
        ⑥ 就利用这个区间找到相应的电梯导航小li,添加active类
     -->

    <div class="box">
        <div class="floor1 box-item">floor1</div>
        <div class="floor2 box-item">floor2</div>
        <div class="floor3 box-item">floor3</div>
        <div class="floor4 box-item">floor4</div>
        <ul class="navs">
            <li class="nav-item active">floor1</li>
            <li class="nav-item">floor2</li>
            <li class="nav-item">floor3</li>
            <li class="nav-item">floor4</li>
        </ul>
    </div>
    <script>
        const navs = document.querySelector('.navs')
        const boxItems = document.querySelectorAll('.box-item')
        const navItems = document.querySelectorAll('.nav-item')
        // 内容区 -> 电梯导航
        window.addEventListener('scroll', function () {
            let n = document.documentElement.scrollTop
            // 当滚动到某一位置时,就让电梯导航显示出来
            if (n >= 100) {
                navs.classList.add('show')
            } else {
                navs.classList.remove('show')
            }

            // 滚动页面激活对应导航栏
            // 先移除其他active类
            const old = document.querySelector('.navs .active')
            old && old.classList.remove('active')
            // 判断当前滑动的页面距离在哪个盒子的区间里,给对应的导航添加active类
            // if (n >= boxItems[0].offsetTop & n < boxItems[1].offsetTop) {
            //     navItems[0].classList.add('active')
            // } else if (n >= boxItems[1].offsetTop & n < boxItems[2].offsetTop) {
            //     navItems[1].classList.add('active')
            // } else if (n >= boxItems[2].offsetTop & n < boxItems[3].offsetTop) {
            //     navItems[2].classList.add('active')
            // } else if (n >= boxItems[3].offsetTop) {
            //     navItems[3].classList.add('active')
            // }
			// 直接判断当前滑动距离是否超过每个大盒子的offsetTop值,超过了就说明在该盒子区间内
            for (let i = 0; i < boxItems.length; i++) {
                if (n >= boxItems[i].offsetTop) {
                     let old = document.querySelector('.active')
                     old && old.classList.remove('active')
                     navItems[i].classList.add('active')
                }
             }
        })

        // 电梯导航 -> 内容区
        for (let i = 0; i < navItems.length; i++) {
            navItems[i].addEventListener('click', function () {
                document.documentElement.scrollTop = boxItems[i].offsetTop
            })
        }

    </script>
</body>

</html>

你可能感兴趣的:(JavaScript,javascript,前端)