floor电梯导航
平时在pc端浏览一些电商网页,就会发现有这麽一样功能:
- 当页面滚动到某一块区域,侧导航栏会让对应的那部分高亮显示,
- 在点击侧导航的某个区域,页面也会自动滚动到这区域
就如下图所示
那么这个功能使用原生js如何去写,思路是怎么样的
思路:
- 当页面滚动到指定位置就不会在滚动,当页面小于设置的指定位置,就能继续滚动
- 当鼠标点击侧导航栏中元素,页面会滚动到该元素对应的那部分区域
- 当页面滚动到侧导航中设定好的区域,侧导航就会高亮某个元素
HTML代码
主要有两部分,导航栏和floor区域
<div class="subnav">
<ul>
<li><a href="javascript:;">手机</a></li>
<li><a href="javascript:;">电脑</a></li>
<li><a href="javascript:;">平板</a></li>
<li><a href="javascript:;">笔记本</a></li>
</ul>
</div>
<div class="floor">
<div class="shouji">
<h1>
我是手机区域
</h1>
</div>
<div class="diannao">
<h1>
我是电脑区域
</h1>
</div>
<div class="pingban">
<h1>
我是平板区域
</h1>
</div>
<div class="bijiben">
<h1>
我是笔记本区域
</h1>
</div>
</div>
CSS代码
<style>
* {
margin: 0;
padding: 0;
}
body {
position: relative;
}
.floor {
width: 1200px;
margin: auto;
}
.floor div {
height: 500px;
border: 1px solid #ccc;
margin-bottom: 10px;
}
h1 {
text-align: center;
}
.subnav {
position: absolute;
top: 800px;
left: 50%;
margin-left: 650px;
}
.subnav ul li {
list-style: none;
width: 70px;
height: 70px;
border: 1px solid #ccc;
text-align: center;
line-height: 70px;
}
footer {
width: 1200px;
margin: auto;
height: 500px;
background-color: #ccc;
border: 1px solid #ccc;
margin-bottom: 10px;
}
</style>
javascript代码
<script>
var subnav = document.querySelector('.subnav');
var li = document.querySelectorAll('.subnav li');
var floor = document.querySelector('.floor');
var diannao = document.querySelector('.diannao');
//1.如果页面滚动到电脑区域就让subnav固定到当前位置,否则就还是相对定位
var diannaoTop = diannao.offsetTop;
var subnavTop = subnav.offsetTop - diannaoTop
document.onscroll = function () {
if (window.pageYOffset >= diannaoTop) {
subnav.style.position = 'fixed';
//此时侧导航的top值就是没滚动前该元素offsetTop-滚到目标位置的offsetTop值
subnav.style.top = subnavTop + 'px';
} else {
subnav.style.position = 'absolute';
subnav.style.top = '800px'
}
console.log(flag);
if (flag) {
//3.頁面滚动到数组中指定区域,让对应的侧导航显示
list.forEach((item, index) => {
if (window.pageYOffset >= item) {
for (var i = 0; i < li.length; i++) {
li[i].style.backgroundColor = ''
}
li[index].style.backgroundColor = 'pink'
}
})
}
}
var list = [floor.children[0].offsetTop, floor.children[1].offsetTop, floor.children[2].offsetTop, floor.children[3].offsetTop]
//2.在li中点谁谁高亮,并且要滚动到相应的位置
var flag = true
for (var i = 0; i < li.length; i++) {
li[i].setAttribute('data-index', i);
li[i].onclick = function () {
//在点击时候页面肯定会滚动,所以上面的滚动事件会影响到元素背景显示,这时候就需要在点击之后停止页面滚动的监听,滚动结束在开启
flag = false;
for (var i = 0; i < li.length; i++) {
li[i].style.backgroundColor = ''
}
this.style.backgroundColor = 'pink';
//获取当前点击的li索引
var index = this.getAttribute('data-index');
//滚动的距离应该是对应数组中的位置
animate(window, list[index], function () {
//动画滚动完成,让flag变为true,可以继续监听页面滚动事件了
flag = true;
})
}
}
//封装一个函数,主要是实现页面可以滚动
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(() => {
var tept = (target - obj.pageYOffset) / 10;
tept = tept > 0 ? Math.ceil(tept) : Math.floor(tept);
if (window.pageYOffset == target) {
clearInterval(obj.timer);
callback && callback()
}
console.log(tept);
window.scroll(0, window.pageYOffset + tept)
}, 30)
}
</script>