常用的功能,当前页面模块锚点菜单固定跟随,当窗口滚动到某个模块时,当前锚点菜单高亮显示。思路是先获取每个模块距离顶部的大小,存到一个数组里,滚动的时候获取滚动的距离,再遍历数组对比当前滚动距离的值,如果大于滚动距离的值,就是当前锚点。或者每滚动一次,就遍历获取各锚点模块距离顶部的大小一次,再进行对比,但感觉这样性能会差很多,推荐前者。

HTML代码:
<div id="wrapper"> <nav id="menu"> <ul class="set-mp"> <li data-item="module-1"> <a href="javascript:void(0);">模块一</a> </li> <li data-item="module-2"> <a href="javascript:void(0);">模块二</a> </li> <li data-item="module-3"> <a href="javascript:void(0);">模块三</a> </li> <li data-item="module-4"> <a href="javascript:void(0);">模块四</a> </li> </ul> </nav> <main id="module"> <section class="module-item" data-module="module-1" style="background-color: #b9925a;"> 模块一 </section> <section class="module-item" data-module="module-2" style="background-color: #eee;"> 模块二 </section> <section class="module-item" data-module="module-3" style="background-color: #efc;"> 模块三 </section> <section class="module-item" data-module="module-4" style="background-color: #fa7;"> 模块四 </section> </main> </div>
CSS代码:
/*html*/
html {font-size:100px;}
/*wrapper*/
#wrapper {
padding:0.5rem;
}
/*menu*/
#menu {
margin-bottom: 0.5rem;
position: sticky;
top:0.1rem;
z-index: 10;
ul {
margin:0;
display: flex;
}
li {
margin-right: 0.2rem;
}
a {
display: block;
background-color: #f6f6f6;
color:#333;
width: 5em;
height: 2.5em;
line-height: 2.5em;
text-align: center;
}
.current {
a {
background-color:#b9925a;
color:#fff;
}
}
}
/*module*/
#module {
.module-item {
height: 30vw;
}
}JS代码:
<script>
let $module = document.querySelectorAll('.module-item');
let $element = [];
$module.forEach(element => {
let $moduleName = element.dataset.module;
let $offsetTop = element.offsetTop - window.innerHeight/2;
$element.push({top:$offsetTop, module:$moduleName});
});
let $lastScrollY = window.scrollY;
let $currentElement;
function scrollHandler(){
let $currentScrollY = window.scrollY;
if(Math.abs($currentScrollY - $lastScrollY) > 0){
$element.forEach(element=>{
if($currentScrollY > element.top){
$currentElement = element.module;
$selector = '[data-item="'+element.module+'"]';
document.querySelector($selector).classList.add('current');
//$($selector).addClass('current').siblings('li').removeClass('current'); 如果使用jQuery,下面那个遍历就不需要了
}
});
$element.forEach(element=>{
if(element.module != $currentElement){
$selector = '[data-item="'+element.module+'"]';
document.querySelector($selector).classList.remove('current');
}
});
$lastScrollY = $currentScrollY;
}
requestAnimationFrame(scrollHandler);
}
requestAnimationFrame(scrollHandler);
</script>也可以按思路使用jQuery写,换成scroll()代码数量可以省一点。