上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
題目要求我們使用 CSS 做出類似上方的菜單圖示動畫,並在點擊後,三條水平線會旋轉、縮放,形成交叉的圖示。
<div class="frame">
<div class="center">
<div class="menuIcon">
<div class="line line1 noAnimate"></div>
<div class="line line2 noAnimate"></div>
<div class="line line3 noAnimate"></div>
</div>
</div>
</div>
我先將三條線條由三個 div
元素構成,統一命名為 .line
。並在外面使用 .menuIcon
包起來,加入了 cursor: pointer
,確保滑鼠指上 Icon 圖示範圍時,都會顯示「手指」的滑鼠圖案。
點擊後使用JS在 .menuIcon
上加上一個 .active
的 class,它會觸發動畫。
MenuIcon 中的三個線條,我使用同一個 class 來管理他們三個的樣式,確保看起來是一樣的,並根據不同的需求給予特定的動畫效果。
並且在這裡我使用了變數來定義線條的高度、間距和位移,這樣當需要調整時,只需修改變數即可,方便管理。
$menuIcon_heignt: 8px;
$menuIcon_spaceY: $menuIcon_heignt * 2;
$resetMenuIconOriginSpace: $menuIcon_spaceY + $menuIcon_heignt;
.menuIcon {
width: 80px;
cursor: pointer;
}
.line {
width: 80px;
height: $menuIcon_heignt;
border-radius: 3px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
background: white;
}
.line2 {
margin: $menuIcon_spaceY 0;
}
一開始的 HTML 中就加上了 noAnimate
的樣式,所以一開始是沒有動畫的。
我使用 .active
來控制是否播放動畫,並在切換成 .active
時,使用JS移除 noAnimate
的樣式。
// 沒有 active 時的返回動畫 & 沒有動畫時畫面
.line1 {
animation: animate-line-1-back ease-in-out .7s forwards}
.line2 {
margin:$menuIcon_spaceY 0;
animation: animate-line-2-back ease-in-out .7s forwards
}
.line3 {animation: animate-line-3-back ease-in-out .7s forwards}
.noAnimate {
-webkit-animation: none !important;
animation: none !important;
}
// active 後的動畫
&.active {
.line1 {animation: animate-line-1 .7s forwards}
.line2 {animation: animate-line-2 .7s forwards}
.line3 {animation: animate-line-3 .7s forwards}
}
當用戶點擊時, .active
被加入在 .menuIcon
上,所以 .active
區塊的 CSS 被套用,動畫開始播放,這邊我使用了 forwards
讓動畫只會播放一次。
第一條線先使用了 translate(x,y)
的特性達成向下移動到 .menuIcon
的中間跟第二條線重疊,並做 rotate(45)
旋轉 45 度。
第二條線則使用 transform: scale(0)
做到縮小並搭配 opacity: 0
在視覺上消失。
第三條線一樣使用了 translate(x,y)
的特性向上移動到跟第二條線重疊,再旋轉 135 度並向上移動。
如此以來,第一條線跟第三條線就完美的話出一個 X 的圖案。
這邊 translate
的位移距離,我使用了變數計算,由於要將第一條線跟第三條線都移動到跟第二條線同樣位置,可以算出位移的距離必須是「一條線的高度,加上他們之間的間距」,等到他們三條線重疊後才開始旋轉。
@keyframes animate-line-1 {
0% { transform: translate(0, 0) rotate(0); }
50% { transform: translate(0, $resetMenuIconOriginSpace) rotate(0); }
100% { transform: translate(0, $resetMenuIconOriginSpace) rotate(45deg); }
}
@keyframes animate-line-2 {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(0); opacity: 0; }
}
@keyframes animate-line-3 {
0% { transform: translate(0, 0) rotate(0); }
50% { transform: translate(0, -$resetMenuIconOriginSpace) rotate(0); }
100% { transform: translate(0, -$resetMenuIconOriginSpace) rotate(135deg); }
}
這一題看起來考驗的是你能否熟練的操作動畫,關鍵點包括:
@keyframes
定義每條線條的動畫過程,讓線條依次旋轉、位移、縮放,形成菜單開關效果。那今天就先到這裡,明天我們再繼續來玩下一題。