一個能氣死前端的按鈕
最近在網(wǎng)上刷到一個短視頻——怎么用一個按鈕氣死前端, 設(shè)計師與程序員的矛盾就是的這么產(chǎn)生的。

這個夜間模式切換開關(guān)效果看著很是炫酷,但確實有難為我們前端人員的嫌疑。

我相信所有前端程序員的心里是

萬馬奔騰·······
不管效果看起來多么復(fù)雜,聰明勇敢的前端人總是能想出辦法來實現(xiàn),最近就看到codepen上的大神就把這個切換效果做出來了。純純硬核代碼完全實現(xiàn),源代碼已在文末整理好。我們來分析一下大神是怎么搞定這個表態(tài)的效果的!
?動效分析
基于開關(guān)的動畫效果可以將相關(guān)動畫步驟進(jìn)行模塊拆分,大概可以拆分為下列模塊:

首先我們可以將代碼拆分為幾大模塊, 來一一實現(xiàn)。
首先背景是根據(jù)開關(guān)整個頁面背景換為暗色。
開關(guān)的內(nèi)部從太陽變成月亮,圓形由黃變灰。
按鈕內(nèi)部背景色,由藍(lán)變黑。
按鈕內(nèi)部有三個透明度不一的大圓跟隨切換
開關(guān)狀態(tài)為白天的時候,會有兩朵云彩其中并有個飛機飛過。
開關(guān)狀態(tài)為黑夜的時候,會有星星閃爍,還有宇航員熊飛過。
主要的動效就是這些,具體的還有很多細(xì)節(jié),比如開關(guān)邊緣的陰影效果,狀態(tài)切換時候的貝塞爾曲線效果,等等,我們這篇文章主要解析核心代碼,細(xì)節(jié)的代碼也會在全代碼文件里,有興趣的可以去研究!
?需要的知識點
在開始寫代碼之前我們知道這幾個知識點。首先,是以元素以aria- 開頭的屬性。aria 英文全稱:Accessible Rich Internet Application,翻譯成中文就是:可訪問的富互聯(lián)網(wǎng)應(yīng)用程序。其實它是一組屬性,定義了使殘疾人更容易訪問 web 內(nèi)容和 web 應(yīng)用程序(尤其是使用JavaScript開發(fā)的應(yīng)用程序)的方法。
這類屬性的作用是為了增強網(wǎng)頁在殘障輔助閱讀設(shè)備上的識別讀取。aria 是一種比較新的輔助訪問技術(shù),用來彌補 HTML 和 JS 本身對可訪問性方面的不足。支持 aria 并不是必須或者強制的,但是支持 aria 會讓你的應(yīng)用變得更友好,更健壯。
我們會用到,aria-pressedARIA屬性,指示按鈕的狀態(tài)打開關(guān)閉混合。他可以表示:
aria-pressed="false":可以表示按鈕為關(guān)閉。
aria-pressed="true":可以表示按鈕為開啟
aria-pressed="mixed":可以表示按鈕為混合狀態(tài),
其次是CSS函數(shù) var()此函數(shù)用于引用先定義的變量值。語法:var(--variable-name, default-value),--variable-name 表示變量名稱,以兩個連字符(--)開頭,是任何自定義名稱。default-value 是可選的,表示在指定變量未定義或無效時要使用的默認(rèn)值。
舉個栗子假設(shè)定義 --dark ,當(dāng)其值為1的時候,最終的代碼則是 scale: 1,如果 --dark 沒有定義則最終的代碼是 scale: 0:
這些變量讓我們更輕松地維護(hù)更新。所以我們可以得到:
這樣我們也就得到--dark 的值,這樣也就可以控制整體頁面的明暗,顏色等屬性。
我們寫這個按鈕會用到很多這個屬性,來控制元素的隱藏顯示和一些動畫效果
?
硬核代碼實現(xiàn)
按鈕背景切換
我們開始研究代碼的實現(xiàn)首先實現(xiàn)開關(guān)內(nèi)部背景顏色的切換,核心代碼如下:
我們通過--dark 的變化更改 background ,也就是 --sky 和 --night 的值,
(tips:hsl 格式的色值,后面兩個參數(shù)的值是需要百分比格式的值)
整個頁面的背景切換是在按鈕點擊的時候
就會給body設(shè)置 data-dark-mode 屬性。
通過 data-dark-mode 得到不同的值。
按鈕內(nèi)部的背景色切換

然后就是按鈕內(nèi)部的太陽轉(zhuǎn)變?yōu)樵铝?,也就是黃色變成灰色。
整個過程我們發(fā)現(xiàn),切換后的灰色
然后是開關(guān)內(nèi)部的圓由黃色(太陽的效果)切換為灰色(月亮的效果)
觀察后發(fā)現(xiàn),切換動畫中,灰色圓由右至左的覆蓋黃色圓, 灰色圓層級高于黃色。
那么我們不難發(fā)現(xiàn),效果的實現(xiàn)方式可以用定位和父子元素,即灰色圓是黃色的子元素。
動畫過程:
1)整個圓從左往右平移當(dāng) --dark 無定義時最終為0當(dāng)---dark 為1時,需要平移當(dāng)前總寬度減去自身圓的寬度的距離,即「3 / 8 * var(--width)」。
2)圓內(nèi)的動畫月亮的背景元素向左平移X軸的100%,之后修改X軸為0%。

再加上過渡動畫
外部的父元素增加了 overflow: hidden,所以默認(rèn)平移X軸100%是不可見的,大家看下面沒有增加 overflow: hidden 代碼的效果就更清晰實現(xiàn)的原理了。

背景透明圓的切換動畫
這個很簡單了radial-gradient 徑向漸變繪制三層背景色,掌握好色值漸變開始和結(jié)束以及大小。將中心定位于太陽的中心。和太陽做一樣的平移動畫就可以了。
星空云朵切換動畫
因為動效比較復(fù)雜,我們可以用svg來實現(xiàn),源代碼就放在最后的源代碼里了,云朵分成兩個顏色,所有要有兩個SVG的代碼,所以
白天狀態(tài)的云朵,并不是左右平移,而是上下,只需改變Y軸的值。
星星閃爍的效果其實就是通svg元素設(shè)置縮放動畫,可以給不同的星星設(shè)置不同的執(zhí)行時間和延遲執(zhí)行時間。
宇航員 & 小飛機
這兩個元素都有動畫效果,宇航員一邊飄過一邊旋轉(zhuǎn),小飛機也緩緩上升。
最后
到了這的我們基本就已經(jīng)搞定了整個按鈕的核心功能,實現(xiàn)了交互效果,但有一些細(xì)節(jié)的陰影,過渡,本塞爾曲線等沒有進(jìn)行具體的介紹。