功能描述:
当滚动条滑到某个位置时,显示电梯导航;
当用户滚动滚动条时,让电梯导航的选中状态和当前滚动到的区域保持一致;
当用户点击电梯导航时,滚动条滚动到被点击导航对应的区域
准备工作:
首先将jQuery文件以及你自己的js文件引入你的html里,jq文件要放在上面
<script src="js/jquery.min.js"></script> <script src="js/index.js"></script>
HTML代码:
1 <body> 2 <div class="slider-bar"> 3 <ul> 4 <li>头部区域</li> 5 <li class="current">导航区域</li> 6 <li>第一部分</li> 7 <li>第二部分</li> 8 <li>第三部分</li> 9 <li>底部区域</li> 10 </ul> 11 </div> 12 <div class="header w">头部区域</div> 13 <div class="banner w">banner区域</div> 14 <div class="main w">主体部分1</div> 15 <div class="main w">主体部分2</div> 16 <div class="main w">主体部分2</div> 17 <div class="footer w">footer部分</div> 18 </body>
1 <style> 2 * { 3 margin: 0; 4 padding: 0; 5 } 6 li { 7 list-style: none; 8 } 9 .slider-bar { 10 display: none; 11 position: fixed; 12 left: 47%; 13 top: 160px; 14 margin-left: 600px; 15 width: 45px; 16 height: 305px; 17 background-color: pink; 18 cursor: pointer; 19 overflow: hidden; 20 } 21 .slider-bar li { 22 font-size: 15px; 23 padding: 5px; 24 border-bottom: 1px solid #fff; 25 } 26 .slider-bar li:hover { 27 background-color: red; 28 color: #fff; 29 } 30 .current { 31 background-color: red; 32 color: #fff; 33 } 34 .w { 35 width: 1100px; 36 margin: 10px auto; 37 } 38 .header { 39 height: 150px; 40 background-color: purple; 41 } 42 .banner { 43 height: 300px; 44 background-color: skyblue; 45 } 46 .main { 47 height: 500px; 48 background-color: yellowgreen; 49 } 50 .footer { 51 height: 300px; 52 background-color: orange; 53 } 54 </style>
具体功能实现:
1. 当用户滑动到banner区域时,显示电梯导航。封装成一个函数toggleTool()
1 function toggleTool() { 2 if($(document).scrollTop() > $(".banner").offset().top - 1) { 3 $(".slider-bar").fadeIn(); // fadeIn()淡入(显示) 4 } else { 5 $(".slider-bar").fadeOut(); // fadeOut()淡出(隐藏) 6 } 7 }
2. each()遍历所有模块,让电梯导航的选中状态和对应模块区域保持一致。封装成一个函数eachTool()
如果滚动上去的高度($(document).scrollTop())大于模块距离文档顶部的距离($(ele).offset().top),说明滚动到了相应模块。给对应的电梯导航添加current类(选中状态),并移除其他导航的current类;
但是如果footer部分太短,那footer对应的导航永远也不会成选中状态,所以要再写一个判断,判断是否滚动到底部;
当(滚上去的高度)+(当前窗口的高度)>=(整个文档的高度)时说明滚动到了底部,给footer添加current 并移除其他current
1 function eachTool() { 2 if(flag) { // flag互斥锁 当它为true时才执行里边的代码 3 $(".w").each(function(i, ele) { // i是索引,ele是遍历对象 4 // 减1是为了解决一个小bug 5 if($(document).scrollTop() > $(ele).offset().top - 1) { 6 // 给对应导航添加current类,并移除其他导航的current类(li里就这一个类,写不写上current都行) 7 $(".slider-bar li").eq(i).addClass("current").siblings().removeClass(); 8 } else if($(window).scrollTop() + $(window).height() >= $(document).height() - 1) { 9 // 当页面滚到底部时,给footer对应的导航添加current类 10 var footIndex = $(".slider-bar li").length - 1; 11 $(".slider-bar li").eq(footIndex).addClass("current").siblings().removeClass(); 12 } 13 }) 14 } 15 }
给window对象绑定滚动事件,当页面滚动时调用上面那两个函数;
当然,为了防止用户刷新页面时导航条显示不正确,所以当页面加载完时我们先调用一次
1 toggleTool(); 2 eachTool(); 3 $(window).scroll(function(e) { 4 toggleTool(); 5 eachTool(); 6 })
3. 用户点击导航,让滚动条滚到对应的区域;
用户点击导航时页面会滚动,就会触发页面滚动事件,会执行eachTool()里的背景选择(选中状态),所以点击导航后先让flag改为false,禁止执行eachTool()里的内容;
获取用户当前点击的li的索引index,正好对应的就是相应模块的索引,知道了是哪个模块 就可以算出这个模块距离文档顶部的距离。调用动画函数animate()让滚动条滚动到这个高度;
执行完动画后要把flag改为true,不然flag永远是false,就没办法执行eachTool()里的内容
1 $(".slider-bar li").click(function(e) { 2 flag = false; 3 // 将模块距离顶部的高度,赋值给current 4 var current = $(".w").eq($(this).index()).offset().top; // $(".w").eq(index) 选择器,选择第几个元素 5 $("html").stop().animate({ // 调用动画前先stop()停止其他未完成的动画(解决排队问题) 6 scrollTop: current 7 }, function() { // 回调函数,动画完成后执行 8 flag = true; 9 }) 10 // 点击添加current类(选中状态) 并移除兄弟节点的current类 11 $(this).addClass("current").siblings().removeClass(); 12 })
完整JavaScript代码:
1 $(function() { 2 // 节流阀(互斥锁) 用来解决一个小bug(当用户点击导航条时,页面滚动会触发eachTool()里的内容,当我们点击时不需要触发eachTool()) 3 var flag = true; 4 // 当用户滑动到banner区域,显示电梯导航。封装成一个函数toggleTool() 5 function toggleTool() { 6 if($(document).scrollTop() > $(".banner").offset().top - 1) { 7 $(".slider-bar").fadeIn(); // fadeIn()淡入(显示) 8 } else { 9 $(".slider-bar").fadeOut(); // fadeOut()淡出(隐藏) 10 } 11 } 12 // each()遍历所有模块,让电梯导航和对应模块保持一致。封装成一个函数eachTool() 13 function eachTool() { 14 if(flag) { 15 $(".w").each(function(i, ele) { // i是索引,ele是遍历对象 16 // 如果滚动上去的高度大于模块距离文档顶部的距离,说明滚动到了相应模块(减1是为了解决一个小bug) 17 if($(document).scrollTop() > $(ele).offset().top - 1) { 18 // 给对应的电梯导航添加current类,并移除兄弟的current类(li里就这一个类,写不写上current都行) 19 $(".slider-bar li").eq(i).addClass("current").siblings().removeClass(); 20 // 如果footer部分太短,那footer对应的导航永远也不会亮了,所以要再写一个判断↓判断是否滚动到底部 21 } else if($(window).scrollTop() + $(window).height() >= $(document).height() - 1) { 22 // 当页面滚到底部时,给footer对应的导航添加current类 23 var footIndex = $(".slider-bar li").length - 1; 24 $(".slider-bar li").eq(footIndex).addClass("current").siblings().removeClass(); 25 } 26 }) 27 } 28 } 29 // 先调用两个函数,以防用户刷新页面后不显示 30 toggleTool(); 31 eachTool(); 32 $(window).scroll(function(e) { 33 toggleTool(); 34 eachTool(); 35 }) 36 37 // 用户点击导航,让滚动条滚到相应模块 38 $(".slider-bar li").click(function(e) { 39 // 点击li页面也会滚动,就会触发页面滚动事件,会执行eachTool()里的背景选择 40 // 所以点击li后让flag为false,禁止执行eachTool()里的内容 41 flag = false; 42 // $(this).index()获取用户当前点击的li的索引,正好对应的就是相应模块索引 43 // 得到相应模块索引就可以算出这个模块距离顶部的高度,赋值给current 44 var current = $(".w").eq($(this).index()).offset().top; // $(".w").eq(index) 选择器,选择第几个元素 45 $("html").stop().animate({ // 调用动画前先stop()停止其他未完成的动画(解决排队问题) 46 scrollTop: current 47 }, function() { // 回调函数,动画执行完后执行 48 flag = true; // 让flag变为true,不然flag永远是false,没办法执行eachTool()里的内容 49 }) 50 // 点击添加current类 并移除兄弟节点的current类 51 $(this).addClass("current").siblings().removeClass(); 52 }) 53 })