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