iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
自我挑戰組

前進切版之路! CSS微體驗系列 第 18

【踩坑】animation 選單按鈕動起來(實作篇)

前情提要

昨天好好的復習了一下動畫的特性之後
今天就來看看怎麼做這顆按鈕吧!

圖源:https://www.pinterest.com/pin/446067538096146820/

分析步驟

  1. 點擊後開始動作
  2. 漢堡三條線合成一條
  3. 兩條線分別旋轉45度與135度形成叉叉(沒有點擊的話停留在這個狀態)
  4. 再次點擊後照步驟3->2->1 反向進行

?也就是說

  1. 我需要JS監聽點擊事件
  2. 線條要能分開操縱,也就是說不適合用陰影下去做漢堡的線條
  3. 線條合而為一跟旋轉線條事件可以分成兩個動畫來執行
  4. 點擊後回復原狀的動畫可以用反向播放來完成!

HTML

為了方便點擊跟監聽,我用一個div包住製作按鈕的element

<div class="wrap">
  <div id="btn"class="btn-box">
    <div  class="btn"></div>
  </div>
</div>

CSS

漢堡的三條線用.btn與::before::after兩個偽元素組成,以便接下來添加animation動畫

.btn{
  width: 100px;
  height: 10px;
  border-radius:3px;
  background-color: #333;
  position: relative;
  
  transition:background-color .01s .5s;
}
 .btn::before{
    content:"";
    width: 100%;
    height: 10px;
    border-radius:3px;
    background-color: #333;
    position: absolute;
    top: -30px;
  }
  .btn::after{
    content:"";
    width: 100%;
    height: 10px;
    border-radius:3px;
    background-color: #333;
    position: absolute;
    bottom: -30px;
  }

把基本形狀做出來之後
我決定利用JS的監聽事件添加class來控制動畫執行
點一下添加.active (執行動畫1,變成叉叉型態)
再點一下添加.close (執行動畫2,回復原狀)

JS

var btn = document.getElementById("btn")
  btn.addEventListener("click",function(){
    if(btn.classList.contains("active") === true){
      this.classList.add("close");
      this.classList.remove("active");
    }else{
      this.classList.add("active");
      this.classList.remove("close");
    }
})

由於變成叉叉只需要兩條線,且兩個偽元素定位在.btn上面,因此中間.btn的那條直接改成透明,而非讓他成為其中一條交叉的線(因為它轉的話,定位在它上面的偽元素也跟著一起轉,變成大家一起轉啊轉)

多段動畫的部分用,進行分隔,就可以讓一個物件擁有多段動畫效果
注意每一段動畫的animation-fill-mode(動畫播放前/結束後的狀態)做好銜接

動畫運行的秒數部分則需要慢慢調適成最佳的狀態

.btn-box.active .btn{
  background-color: transparent;
  transition:background-color .01s .2s;
}
.btn-box.close .btn::before{
    animation: backturn1 .4s .2s ease-in-out reverse both,
               backmoveDown .3s .55s ease-in  reverse both;          
}
.btn-box.active .btn::before{
    animation:moveDown .3s ease-in forwards,
              turn1 .4s .2s ease-in forwards;
}

.btn-box.close .btn::after{
    animation: backturn2 .45s .1s ease-in reverse both,
               backmoveUp .3s .55s ease-in  reverse both;          
}
.btn-box.active .btn::after{
    animation:moveUp .3s ease-in forwards ,
              turn2 .4s .2s ease-in forwards;
}

@keyframes moveDown{ 
  0%{top: -30px;}
  100%{top:0;}
}
@keyframes backmoveDown{
  0%{top: -30px;}
  100%{top:0;}
}

@keyframes moveUp{
  0%{bottom: -30px;}
  100%{bottom:0;}
}
@keyframes backmoveUp{
  0%{bottom: -30px;}
  100%{bottom:0;}
}

@keyframes turn1{
  0%{transform:rotate(0deg);}
  90%{transform:rotate(50deg);}
  100%{transform:rotate(45deg);}
}
@keyframes backturn1{
  0%{transform:rotate(0deg);}
  90%{transform:rotate(50deg);}
  100%{transform:rotate(45deg);}
}

@keyframes turn2{
  0%{transform:rotate(0deg);}
  90%{transform:rotate(145deg);}
  100%{transform:rotate(135deg);}
}
@keyframes backturn2{
  0%{transform:rotate(0deg);}
  90%{transform:rotate(145deg);}
  100%{transform:rotate(135deg);}
}

做到這裡會發現...回復原狀的動畫跟變成叉叉的動畫是一模一樣的呀!只是加了reverse而已,為什麼不用同一組就好了?!

沒錯...當時我也是這樣想的qaq (坑在這裡)
結果發現動畫會沒作用...
因此才分成兩段來寫> <

最後再幫包著按鈕的div做一點裝飾~讓他更有互動感

.btn-box{
  width: 100px;
  height: 100px;
  padding: 15px;
  display: flex;
  align-items: center;
  border-radius:3px;
  background-color: #afa;
  transition:background-color .5s;
}
.btn-box:hover{ background-color: #8e8;}
.btn-box.active{ background-color: #faa; }
.btn-box.active:hover{  background-color: #e88;}

最後出來的成果!!!
滿滿的!成!就!感!!!

註:在寫多段動畫時,animation-fill-mode就非常重要囉~
如果選錯執行的狀態,就會看到癲癲怪怪的動畫XDDD
另外使用動畫製作的話,一但觸發開始執行就要把流程整個跑完,無法中斷~
codepen實作玩玩看


上一篇
【踩坑】animation 選單按鈕動起來(複習篇)
下一篇
【心得】CSS-transform vs.relative 今天要吃哪一道呢~
系列文
前進切版之路! CSS微體驗30

尚未有邦友留言

立即登入留言