就像上圖這樣的動畫效果 在導航欄里的時候,下劃線跟隨滑鼠移動,滑鼠移出導航欄時,下劃線回到初始位置,同時要適應導航的寬度 為了適應導航的寬度,就不能給導航元素設置 margin,然後將導航元素的 clientWidth 設置給下劃線 然後需要讓下劃線獨立於導航之外,從而保證它的無縫滑動(其實也可以用 ...
就像上圖這樣的動畫效果
在導航欄里的時候,下劃線跟隨滑鼠移動,滑鼠移出導航欄時,下劃線回到初始位置,同時要適應導航的寬度
為了適應導航的寬度,就不能給導航元素設置 margin,然後將導航元素的 clientWidth 設置給下劃線
然後需要讓下劃線獨立於導航之外,從而保證它的無縫滑動(其實也可以用偽類元素實現,不過效果不夠好)
再根據左側導航的寬度總和,計算出下劃線左移的距離
一、基本結構
基於上面的思路,HTML 結構可以設計成這樣:
並將下劃線的 width 和 left 設置為動態 style,在滑鼠滑動時實時修改
然後給 MainHeader 和 Underline 添加 CSS 樣式:
.main {
position: relative;
width: fit-content;
margin: 0 auto;
text-align: center;
}
.nav-underline {
position: absolute;
bottom: 0;
display: block;
height: 2px;
background-color: #000;
transition: all .2s ease-out;
}
二、移動下劃線
因為需要實時修改下劃線的寬度,所以需要監聽 mouseenter 事件,獲取當前元素
但如果導航元素 nav 還有子元素 (比如上面的 nav-title),直接用 event.target 就有問題
經過取捨,我決定獲取 MainHeader 的 childNodes,然後根據 v-for 的 index 去查找對應的導航元素
在對應的事件處理函數裡面,將導航元素的 clientWidth 設置為下劃線的寬度
同時計算當前導航的左側所有導航的寬度之和,作為下劃線的左移距離
setCurrentNav (index) {
// 滑鼠移動到導航時,記錄臨時狀態
this.currentNav = index
this.currentNavStyle = this.getNavStyle(index)
},
getNavStyle (index) { // 根據導航的 index 移動下劃線
let childNodes = this.$refs.MainHeader.childNodes
// 根據當前導航的寬度,設置下劃線的寬度
let width = childNodes[index].clientWidth
// 設置下劃線的預設位置
let left = 0
if (index > 0) {
// 計算左邊導航的總寬度,設置為下劃線的左移距離
for (let i = 0; i < index; i++) {
left += childNodes[i].clientWidth
}
}
return {width, left}
}
最後在 computed 裡面動態修改下劃線樣式
三、完善激活狀態
上面實現了滑鼠移動時候的下劃線跟隨效果
但對於點擊導航後但激活狀態 active 還沒有做處理
在導航元素上添加 click 事件的處理函數,記錄下激活元素的 index
setActiveNav (index) {
// 點擊導航時,設置激活樣式
this.activeNav = index
this.activeNavStyle = this.getNavStyle(index)
}
當滑鼠移出 MainHeader 的時候,下劃線還得回到 active 的位置
上面已經對 navLineStyle() 做了相容處理,所以只需要在滑鼠移出的時候,清空 currentNavStyle 即可
handleLeaveMainHeader () {
// 滑鼠離開導航欄時,重置下劃線狀態
this.currentNavStyle = null
}
四、純CSS實現下劃線跟隨
參考鏈接:https://github.com/chokcoco/iCSS/issues/33
如果對於整個動畫效果的要求不是特別高, 可以用偽類元素實現下劃線跟隨
所以 HTML 結構裡面就不用將下劃線獨立出來
然後使用 after 畫出下劃線
.nav {
position: relative;
overflow: hidden;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 100%;
width: 0;
height: 2px;
background-color: #000;
transition: all 0.3s ease-out;
}
}
這裡設置了 width: 0; left: 100%; 這是為了讓下劃線預設從右向左出現,然後從左向右消失
然後在 hover 狀態下,將對應的 after 設置為 width: 100%; left: 0;
最後使用 CSS 中的相鄰元素選擇器 ( + ) 選擇相鄰的 after,設置左移為 left: 0;
.nav {
&:hover {
&::after {
width: 100%;
left: 0;
}
& + .nav::after {
left: 0;
}
}
}
從而實現相鄰下劃線 after 能從左向右出現,動畫連起來就像是下劃線跟隨滑鼠滑動了
這種方式不夠完美,但僅僅需要幾行 CSS 就能實現,還是非常厲害的