<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CSS 實(shí)現(xiàn)按鈕點(diǎn)擊動(dòng)效的套路

          共 5508字,需瀏覽 12分鐘

           ·

          2022-02-22 19:28

          作者:XboxYan

          來源:SegmentFault  思否社區(qū) 


          在 Web 中,大部分按鈕可能都是平平無奇的,有時(shí)候?yàn)榱藦?qiáng)調(diào)品牌特殊或者滿足特殊功能,可能需要給按鈕添加一點(diǎn)點(diǎn)擊動(dòng)效。比如,用過 Ant Design 的小伙伴應(yīng)該都能發(fā)現(xiàn),在點(diǎn)擊按鈕的時(shí)候會有一個(gè)很微妙的水波動(dòng)畫



          這就非常有特色了,看到這樣的按鈕自然會聯(lián)系上 Ant Design 。


          動(dòng)畫過程其實(shí)不復(fù)雜,看了一下官方的實(shí)現(xiàn),是通過 js 動(dòng)態(tài)更改屬性實(shí)現(xiàn)的,在點(diǎn)擊的時(shí)候,改變屬性,觸發(fā)動(dòng)畫,當(dāng)動(dòng)畫結(jié)束之后,再將該屬性還原(還原是為了保證下次點(diǎn)擊仍然有動(dòng)畫),如下



          看著好像有點(diǎn)麻煩?其實(shí),這種效果也是可以純 CSS 實(shí)現(xiàn)的,而且還能實(shí)現(xiàn)其他更多有趣的效果



          一起看看吧~


          一、CSS 過渡動(dòng)畫



          通常 CSS 中實(shí)現(xiàn)動(dòng)畫有兩種思路,transitionanimation。一般而言,簡單的、需要主動(dòng)觸發(fā)(:hover 、:active或者動(dòng)態(tài)切換類名等)的可以用transition實(shí)現(xiàn),其他的都可以用animation。


          回到這個(gè)例子,動(dòng)畫足夠簡單了,就兩個(gè)變化,而且需要主動(dòng)觸發(fā)(這里是點(diǎn)擊,可以想到:active),所以優(yōu)先考慮用transition來實(shí)現(xiàn)。


          觀察整個(gè)動(dòng)畫,其實(shí)就是兩個(gè)效果疊加而成


          1. 陰影不斷擴(kuò)大
          2. 透明度不斷降低

          那么,這個(gè)動(dòng)畫(過渡)的兩種狀態(tài)可以這樣來表示

          /* 初始狀態(tài) */
          button{
            opacity: .4;
            transition: .3s;
          }
          /* 擴(kuò)散狀態(tài) */
          button{
            box-shadow: 0 0 0 6px var(--primary-color);
            opacity: 0;
          }

          嗯,兩種狀態(tài)的樣式都寫好了,怎么觸發(fā)點(diǎn)擊呢?


          二、CSS 點(diǎn)擊動(dòng)畫



          先完善一下基本樣式,假設(shè) HTML 結(jié)構(gòu)如下

          <button class="button">Default</button>

          簡單美化一下

          :root{
            --primary-color: royalblue;
          }
          .button{
            padding: 5px 16px;
            color: #000000d9;
            border: 1px solid #d9d9d9;
            background-color: transparent;
            border-radius: 2px;
            line-height: 1.4;
            box-shadow: 0 2px #00000004;
            cursor: pointer;
            transition: .3s;
          }
          .button:hover{
            color: var(--primary-color);
            border-color: currentColor;
          }

          然后添加陰影擴(kuò)散動(dòng)畫,為了方便透明度的控制,這里用::after偽類單獨(dú)渲染

          .button::after{
            content: '';
            position: absolute;
            inset: 0;
            border-radius: inherit;
            opacity: 0.4;
            transition: .3s;
          }

          如果按照正常的思路通過:active來觸發(fā)過渡動(dòng)畫,可能會這樣來實(shí)現(xiàn)

          .button:active::after{
            box-shadow: 0 0 0 6px var(--primary-color);
            opacity: 0;
          }

          效果如下:


          嗯,好像不大對勁?接著往下看

          三、CSS 過渡重置



          為什么會有上面這種現(xiàn)象呢?這里提一下:active:active只有在鼠標(biāo)按下時(shí)才會起作用,通常在點(diǎn)擊一個(gè)按鈕時(shí),都是輕輕地點(diǎn)擊,而不是長按,如果在:active上添加動(dòng)畫,那么在鼠標(biāo)抬起的時(shí)候,動(dòng)畫一般都沒有結(jié)束,所以會導(dǎo)致在鼠標(biāo)抬起的時(shí)候,動(dòng)畫馬上就停止了,如果是transition,還會有一個(gè)“回退”的過渡效果。

          那么,有沒有什么方法可以只在鼠標(biāo)抬起的時(shí)候產(chǎn)生動(dòng)畫呢?

          我的實(shí)現(xiàn)是這樣的,假設(shè)默認(rèn)就是有陰影(透明度為0)的狀態(tài),在:active的時(shí)候迅速去除陰影(這里的“迅速”,是指取消按下去的過渡動(dòng)畫),然后由于默認(rèn)是有過渡的,所以鼠標(biāo)抬起的時(shí)候陰影就回退到有陰影的狀態(tài)了,這樣可以保證按下去是沒有動(dòng)畫的,抬起來觸發(fā)過渡動(dòng)畫

          整個(gè)流程其實(shí)是這樣:


          取消過渡動(dòng)畫也很簡單,設(shè)置時(shí)長為 0 就行了,代碼實(shí)現(xiàn)就是這樣

          .button::after{
            /*其他樣式*/
            opacity: 0;
            box-shadow: 0 0 0 6px var(--primary-color);
            transition: .3s;
          }
          /*點(diǎn)擊*/
          .button:active::after{
            box-shadow: none;
            opacity: 0.4;
            transition: 0s; /*取消過渡*/
          }

          然后,神奇的效果就出來了!


          這樣就實(shí)現(xiàn)了和 Ant Design 幾乎相同的點(diǎn)擊效果


          四、其他動(dòng)效案例



          上面其實(shí)提供了一種思路,只要是這種點(diǎn)擊動(dòng)畫,都可以采用這種方式來實(shí)現(xiàn)。比如這樣一個(gè)刷新按鈕,需要點(diǎn)擊的時(shí)候轉(zhuǎn)一下


          用這種思路就很容易了,這個(gè)例子比上面那個(gè)要簡單一些,畢竟只有旋轉(zhuǎn)變化,沒有透明度變化,核心代碼如下

          .icon{
              transform: rotate(360deg);
              transition: .5s;
          }
          .button:active .icon{
              transform: rotate(0);
              transition: 0s;
          }

          完整代碼可以訪問:https://codepen.io/xboxyan/pen/JjONraR

          整合了更多的 demo


          再比如這樣的點(diǎn)擊粒子動(dòng)效,原理也是相同的


          在之前文章CSS實(shí)現(xiàn)一個(gè)粒子動(dòng)效的按鈕中已經(jīng)有講到,這里就不多說了

          完整代碼可以訪問:https://codepen.io/xboxyan/pen/oNgEEdG


          五、更復(fù)雜的動(dòng)畫



          前面提到過,簡單的動(dòng)畫可以用過渡transition來實(shí)現(xiàn),那么稍微復(fù)雜點(diǎn)的,比如下面這種 “Q彈Q彈” 的按鈕


          這類動(dòng)畫,單純的transition就無能為力了,必須借助animation來實(shí)現(xiàn),原理還是類似。

          先定義一個(gè)動(dòng)畫關(guān)鍵幀

          @keyframes tada {
              from {
                  transform: scale3d(1, 1, 1)
              }
              10%, 20% {
                  transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
              }
              30%, 50%, 70%, 90% {
                  transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
              }
              40%, 60%, 80% {
                  transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
              }
              to {
                  transform: scale3d(1, 1, 1)
              }
          }

          這個(gè)動(dòng)畫來自于 Animate.css 中的 tada,直接 copy 過來就行

          鏈接:https://animate.style/

          然后讓按鈕動(dòng)起來

          .button{
            animation: tada 1s;
          }

          在點(diǎn)擊的時(shí)候重置動(dòng)畫,直接重置動(dòng)畫,animation可能會更好理解一些,這樣在抬起的時(shí)候會重新運(yùn)行動(dòng)畫

          .button:active{
            animation: none;
          }

          這樣就實(shí)現(xiàn)了,是不是出乎意料的容易?

          不過有一點(diǎn)小瑕疵,每次頁面刷新,按鈕會主動(dòng)進(jìn)行一次動(dòng)畫(因?yàn)閯?dòng)畫是自動(dòng)執(zhí)行的),如下


          那么,如何避免首次進(jìn)來時(shí)動(dòng)畫不執(zhí)行呢?

          這里有一個(gè)小技巧,可以在默認(rèn)情況下設(shè)置動(dòng)畫時(shí)長為 0 ,這樣在首次動(dòng)畫執(zhí)行后,馬上就結(jié)束了,然后在 hover時(shí)恢復(fù)默認(rèn)的動(dòng)畫時(shí)長,由于動(dòng)畫已經(jīng)結(jié)束,改變動(dòng)畫時(shí)長也不會觸發(fā)動(dòng)畫再次運(yùn)行,所以實(shí)現(xiàn)就是

          .button{
            animation: jump 0s;
          }
          .button:hover{
            animation-duration: 1s;
          }
          .button:active{
            animation: none;
          }

          這樣刷新頁面就不會再有動(dòng)畫了


          接下來,借助 animate.css 你可以更換任意的動(dòng)畫,比如


          完整代碼可以訪問:https://codepen.io/xboxyan/pen/NWwgWQG

          整合了更多的 demo


          六、總結(jié)和說明



          以上就是關(guān)于 CSS 點(diǎn)擊動(dòng)畫的幾個(gè)套路和一些案例,其實(shí)就是默認(rèn)執(zhí)行動(dòng)畫,點(diǎn)擊時(shí)重置一下就行了。整體來說代碼很簡單,只是理解起來可能不是特別順暢,下面總結(jié)一下實(shí)現(xiàn)要點(diǎn):

          1. 簡單動(dòng)畫用transition,其他用 animation

          2. transition 可以通過設(shè)置時(shí)長為 0 來重置

          3. animation 可以通過設(shè)置 none 來重置

          4. 在 :active 時(shí)重置動(dòng)畫,點(diǎn)擊后會再次運(yùn)行動(dòng)畫

          5. 復(fù)雜的動(dòng)畫可以借助現(xiàn)有的動(dòng)畫庫,例如 anmate.css

          6. 設(shè)置動(dòng)畫時(shí)長為 0 可以避免首次渲染出現(xiàn)動(dòng)畫


          相比 js 實(shí)現(xiàn),CSS 實(shí)現(xiàn)代碼更少,加載更快,無需等待 js 加載完成,體驗(yàn)更優(yōu)(比如天然支持敲空格鍵觸發(fā)),同時(shí)也更容易維護(hù)和使用,直接復(fù)制一個(gè)類名就行了。最后,如果覺得還不錯(cuò),對你有幫助的話,歡迎點(diǎn)贊、收藏、轉(zhuǎn)發(fā)



          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號后臺回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 61
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文无码一区二区三区四区五区六区七区 | 黄a免费视频在线观看 | 大香蕉福利网 | 欧美人与禽性XXXXX杂性 欧美日韩一区二区三区,麻豆 | 翔田千里在线一区二区 |