JS實現網站樓層導航效果


 壹 ❀ 引

我在angularjs中使用錨點這篇文章中,踩坑並簡單實現了樓層導航中點擊小圖標跳轉到對應樓層的功能;但對於樓層導航而言,還有個重要的功能就是,隨着滾動條滾動,達到某層時得同步點亮樓層導航的小圖片。

由於我前面也說了不打算使用JQ,所以想着用JS去實現它,實現並不難,主要得弄清滾動滿足怎樣的條件才應該點亮對應樓層,我們先看看實現效果:

 貳 ❀ 實現思路

第一點,因為是由滾動觸發的樓層判斷,所以肯定離不開onscroll事件

第二點,我們貌似要獲取每個樓層頂端距離視窗頂部的距離,隨着滾動條往下滾動,此距離會不斷縮小,當接近到某個距離時我們判定此樓層入畫,當然其它樓層都滿足此判定。

而JQ提供了一個offset().top方法能獲取這個值,js中只有一個offsetTop屬性,獲取的是距離自己最近position屬性為非static的祖先元素的距離,此距離不隨滾動條滾動而縮小

當然我們有方法模擬計算出offset().top的值,但沒必要,如果你對JQ的offset().top與js的offsetTop有什么區別,以及對如何模擬出JQ的offset().top的值有興趣,可以參照博主這篇文章 JQ的offset().top與js的offsetTop區別詳解

這里我直接引用了我之前博客得到的結論:offset().top = offsetTop - scrollTop(offsetTop 參考對象為根元素)

為了方便理解,我們假設樓層壹頂端距離視窗頂端為0時,此時判定樓層壹入畫,即樓層導航中第一個按鈕應該被點亮。

由於offset().top = offsetTop - scrollTop,此時樓層壹距離頂端已經為0,我們可以得出當樓層壹的offsetTop = scrollTop時,我們認定樓層壹入畫

而當樓層貳入畫時,樓層貳的offsetTop也等於滾動條的距離,此時樓層壹自然會出畫:

那么現在我們得到了判斷樓層入畫的條件,如果某個樓層的offsetTop屬性的值小於等於滾動條距離時(如果用等於條件過於苛刻,很難剛好滾動到這個距離點上),我們點亮對應樓層的導航logo。

為了讓效果更加自然,我們肯定不會真的讓某個樓層緊貼頂部時才判定它滿足條件,肯定是提前某個距離就判定滿足,所以真正的條件應該是offsetTop - 100(這個數字看自己感覺) <= scrollTop

你是否會有,樓層貳入畫時樓層壹依然滿足offsetTop<=scrollTop條件的疑惑?在JQ里面,我們給某個元素添加點亮class的同時,還會清除掉兄弟元素的該class。

所以在JS里面也是如此,我們利用滿足樓層的索引來控制樣式,而后者滿足條件的索引始終會覆蓋前面的索引,所以被點亮的永遠只有一個

現在弄懂了思路,代碼就好些了,下面直接貼上了實現代碼:

 叄 ❀ 實現代碼

HTML部分:

<div class="floor">
    <div style="background: #ffb6b9"></div>
    <div style="background: #fae3d9"></div>
    <div style="background: #bbded6"></div>
    <div style="background: #8ac6d1"></div>
    <div style="background: #fff1ac"></div>
</div>
<ul class="floorNav">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
View Code

CSS部分:

* {
    padding: 0;
    margin: 0;
    list-style: none;
}

.floor>div {
    height: 900px;
    line-height: 900px;
    text-align: center;
    color: #fff;
    font-size: 40px;
}

.floorNav {
    width: 40px;
    height: 200px;
    position: fixed;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    background: #ddd;
}

.floorNav>li {
    height: 40px;
    line-height: 40px;
    text-align: center;
    color: #fff;
}

.active {
    background: #e4393c;
    color: #fff;
}
View Code

JS部分:

//獲取樓層
let floors = document.querySelectorAll(".floor>div");
//獲取樓層導航
let floorNavs = document.querySelectorAll(".floorNav>li");
//滾動監聽
window.onscroll = function () {
    //獲取滾動條高度,兼容ie
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //符合點亮條件的樓層索引
    let activeIndex;
    //樓層導航圖標點亮控制
    floors.forEach((floor, index) => {
        //檢查各樓層頂端距離視窗頂端距離,如果滿足條件則修改樓層圖標
        floor.offsetTop - 100 <= scrollTop ? activeIndex = index : null;
    });
    //根據索引數設置樓層樣式
    floorNavs.forEach((nav, index) => {
        index === activeIndex ? nav.classList.add('active') : nav.classList.remove('active');
    });
};
View Code

需要注意的是,這里我使用了js中操作classList對象的add方法與remove方法,這兩個方法IE並不支持,因為我這邊是不需要考慮IE的,所以就任性了。

如果考慮兼容性,還是得模擬實現JQ的addClass方法,有興趣可以參考博主 js實現 addClass方法,classList與className有什么區別這篇文章。

本文只是提供了一個樓層導航的思路,實現肯定不是很好,若有更佳的做法,歡迎留言討論,那么本文結束。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM