【踩坑】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实作玩玩看


<<:  初学者跪着学JavaScript Day12 : 麻烦的JS加法

>>:  [Day26] Tableau 轻松学 - TabPy 开发流程

How to convert RAW to NTFS file system without losing data?

What should you do if the partition on your extern...

[Day05] JavaScript - 资料型别

资料型别   JavaScript 的型别主要可以分成基本型别 (Primitives)与物件型别 ...

【Day22】:旋转编码器—Encoder

Encoder Encoder也就是编码器,可用於将马达的旋转资讯转换为方波的形式输出,他的构造与原...

Day7 使用 Vercel 发布我们的 Next.js 网站,搭配 Github 实现自动部署

上一篇我们建完 Next.js 专案了,并且能成功在自己的电脑上开发改 code 了!下一步就是要来...

我们注定成不了海贼王

OK!上一篇最後讲了个我亲身体验过会让人掉san值的专案开发经验,但.......那个专案最後还是完...