實現效果:
html代碼:
<div class="sidenav"><ul class="nav-text progressbar"><!-- data-target的值對應要跳轉的模塊的id --><li data-target="module1"><div class="text">錨點名稱</div></li><li data-target="module2"><div class="text">錨點名稱</div></li><li data-target="module3"><div class="text">錨點名稱</div></li><li data-target="module4"><div class="text">錨點名稱</div></li></ul>
</div>
給要跳轉的dom元素id賦值即可。
css:
/* 側邊錨點跳轉 */
.sidenav {z-index: 40;left: 1%;bottom: 15%;min-height: 55px;position: fixed;/* width: 140px; */background: #ffffff;box-shadow: 0px 0px 35px 0px rgba(106, 76, 248, 0.16);border-radius: 8px;padding: 25px 22px 0px 16px;
}.progressbar li {list-style-type: none;/* float: left; width: 33.33%; */position: relative;text-align: center;font-size: 16px;align-items: center;display: flex;height: 42px;max-width: 102px;margin-bottom: 25px;
}.progressbar .text {-webkit-box-orient: vertical;display: -webkit-box;/* width: 64px; */width: 80px;text-align: left;-webkit-line-clamp: 2;overflow: hidden;text-overflow: ellipsis;
color: #333333;
cursor: pointer;
}.progressbar li:before {content: "";text-align: center;width: 12px;height: 12px;
background: #999999;border-radius: 50%;margin-right: 10px;
}.progressbar li:after {/* 偽元素實現li圓點垂直相連的線*/top: -13px;transform: translate(-50%, 0) rotate(90deg);content: "";position: absolute;width: 66%;height: 1px;background: #999999;;left: 6px;z-index: -1;
}.progressbar li:first-child:after {content: none;
}
js:
// 避免點擊事件觸發時,觸發滾動事件增加active類的函數var isProgressBarClick = false;// 獲取懸浮窗的ul元素const moduleList = document.querySelector('.progressbar');var timeoutId = null;// 滾動到對應模塊并添加active類的點擊事件處理函數function scrollToModule(event){isProgressBarClick = true;var aim = event.target;if(event.target.className === 'text'){aim = event.target.parentNode}const targetModuleId = aim.getAttribute('data-target');const targetModule = document.getElementById(targetModuleId);if (targetModule) {// 使用平滑滾動實現滾動效果targetModule.scrollIntoView({ behavior: 'smooth' });// 移除之前被添加的active類const activeItem = document.querySelector('.progressbar li.active');if (activeItem) {activeItem.classList.remove('active');}// 為當前點擊的列表項添加active類aim.classList.add('active');}// 等待錨點跳轉完成后再重置標志變量clearTimeout(timeoutId);timeoutId = setTimeout(function() {isProgressBarClick = false;}, 1000);}$('.progressbar li').click(scrollToModule)$('.progressbar li .text').click(scrollToModule)// 監聽頁面滾動事件window.addEventListener('scroll', handleScroll);function handleScroll() {if(!isProgressBarClick){// 獲取頁面滾動的垂直位置const scrollPosition = window.scrollY;// 遍歷模塊元素,找到當前可見的模塊var activeModuleId = null;var moduleElements = document.querySelectorAll('.module_list>div')for (const moduleElement of moduleElements) {// 用于獲得頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置const { top, bottom } = moduleElement.getBoundingClientRect();// 判斷模塊是否在視口內(至少一半在視口內)if (top <= window.innerHeight / 2 && bottom >= window.innerHeight / 2) {activeModuleId = moduleElement.id;break;}}// 添加active類if (activeModuleId) {// 移除之前被添加的active類const activeItem = document.querySelector('.progressbar li.active');if (activeItem) {activeItem.classList.remove('active');}// 為當前可見的模塊對應的列表項添加active類const activeListItem = document.querySelector(`.progressbar li[data-target="${activeModuleId}"]`);if (activeListItem) {activeListItem.classList.add('active');}}}}// 初始加載時觸發一次滾動事件handleScroll();