CSS 實現 Ant Design官網Logo彩蛋效果

XboxYan發表於2022-01-25

最近專案中 Ant Design 接入比較多,還是非常不錯的。不知道大家有沒有發現這樣的效果,在官網上,如果滑鼠放在Logo上,字母i上的圖示會不停的變化,離開後停止,放上去重新變化,算得上是一個小彩蛋(可能我之前沒發現?),演示如下:

Kapture 2022-01-24 at 23.37.48

不過沒發現也不意外,因為這個效果是 js 實現的,必須等待載入完成才能生效,而官網有時候又特別的慢,比如像這種還在載入的情況下,大概率是不會有以上的hover效果的

image-20220124234154039

嗯,思考了一下,這種效果完全可以用純 CSS 來完成呀,實現成本又低,又能有效避免上述的載入問題,一起看看吧

一、CSS 實現原理

整個實現原理大致如下

  1. 準備一個包含所有小圖示的素材
  2. 建立一個改變背景位置的CSS逐幀動畫
  3. 通過滑鼠 hover 來控制動畫執行

二、素材準備

為了避免多次請求,也為了方便建立動畫,這裡把所有小圖示素材組合在一塊(從官網另存下來的),就像以前的“雪碧圖”一樣,如下

image-20220124234305933

假設 HTML 結構是這樣的

<h1 class="logo">Ant Design</h1>

為了更好的語義化,這裡的文字建議保留,然後通過其他方式隱藏文字(比如透明度),可以將 logo 作為背景圖片,然後可變化的小圖示用偽元素生成(裝飾性的元素都可以用偽元素來生成,保證HTML的整潔),CSS 如下

.logo{
  width: 500px;
  height: 100px;
  position: relative;
  color: transparent;
  background: url('https://imgservices-1252317822.image.myqcloud.com/image/012420220165011/c0e82c29.svg') center/contain no-repeat;
  cursor: pointer;
}
.logo::after{
  content: '';
  position: absolute;
  width: 32px;
  height: 32px;
  background: url('https://imgservices-1252317822.image.myqcloud.com/image/012420220165415/b0005044.svg') 0 / cover no-repeat;
  right: 113px;
  top: -18px;
}

靜態佈局就算出來了

image-20220124234420692

二、CSS 逐幀動畫

然後是動畫,只需要利用 CSS 動畫函式中的 steps() 功能符,就可以實現逐幀動畫

首先定義一個關鍵幀,改變背景位置就行了

@keyframes random {
  to {
    background-position: 100%;
  }
}

這裡小圖示總共有 11 張,相互之間的變化就是 10 步,所以動畫設定如下

.logo::after{
    /*其他樣式*/
  animation: random 1s steps(10) infinite;
}

這樣就得到了一個無限迴圈的逐幀動畫

Kapture 2022-01-24 at 20.07.24

三、CSS動畫的暫停與執行

預設情況下,CSS動畫是預設執行的,但是現在的需求是,只有滑鼠 hover 上去才會動起來。

可能有同學會這樣做,預設情況下沒有動畫,hover 的時候建立動畫,如下

.logo::after{
    /*預設無動畫*/
}
.logo:hover::after{
  animation: random 1s steps(10) infinite;
}

但是這樣做會有兩個問題:

  1. 每次實時建立動畫會有更多的效能消耗
  2. 每次滑鼠離開後位置就還原成初始狀態了

Kapture 2022-01-24 at 20.35.54

因此,這種方式並不可取

除了上述方式可以控制動畫執行之外,還可以通過animation-play-state主動設定暫停,如下

.logo::after{
    /*其他樣式*/
  animation: random 1s steps(10) infinite;
  animation-play-state: paused; /*動畫暫停*/
}

這樣下來,預設就不會動了,然後在hover的時候“執行”就行了

.logo:hover::after{
  animation-play-state: running; /*動畫執行*/
}

效果如下

Kapture 2022-01-25 at 10.33.11

四、指定初始位置

現在預設是小圖示是第一個,如果想指定另外一個,比如❤

image-20220124234803464

這種情況如何處理呢

首先我們想到,可以手動改變背景位置就行了,❤ 在第8個,所以

.logo::after{
  /*其他樣式*/
  background-position: -224px; /* 32 * 7 */
}

效果如下

Kapture 2022-01-24 at 20.43.52

這樣下來,問題更多,由於改變了動畫的起始位置,動畫從第 8 個的地方運動到最右側,左邊的都不經過了,step 也需要重新調整。

除了這種方式,還可以通過動畫的“負延遲”來實現,給動畫新增一個負的延遲後,動畫會提前運動到未來位置

比如這裡想指定到未來第7幀的位置,就可以延遲負的總運動時長的 7/ 10 ,實現如下

.logo::after{
  /*其他樣式*/
  animation-delay: -.7s; /* 7 / 10 * 1s*/
}

這樣就不會影響原有的動畫了,完美實現

Kapture 2022-01-24 at 20.57.22

完整程式碼可以訪問:Ant Design Logo (codepen.io)

附上完整程式碼(最近codepen貌似不太穩定)

.logo{
  width: 500px;
  height: 100px;
  position: relative;
  color: transparent;
  background: url('https://imgservices-1252317822.image.myqcloud.com/image/012420220165011/c0e82c29.svg') center/contain no-repeat;
  cursor: pointer;
}
.logo::after{
  content: '';
  position: absolute;
  width: 32px;
  height: 32px;
  background: url('https://imgservices-1252317822.image.myqcloud.com/image/012420220165415/b0005044.svg') 0 / cover no-repeat;
  right: 113px;
  top: -18px;
  animation: random 1s -.7s steps(10) infinite;
  animation-play-state: paused;
}
.logo:hover::after{
  animation-play-state: running;
}
@keyframes random {
  to {
    background-position: 100%;
  }
}

五、總結和說明

上面就是針對 Ant Design 官網 Logo 效果的 CSS 實現,程式碼量非常少,而且也避免了 js 未載入完成時的問題,體驗更好,下面簡單總結一下

  1. CSS 渲染是及時的,只要頁面可見,就不會影響 CSS 互動
  2. 逐幀動畫可以通過 CSS 動畫 中的 step() 函式實現
  3. CSS 動畫可以自動執行,也可以手動暫停
  4. 通過設定負的延時,可以讓 CSS 動畫提前執行

當然,CSS 的優點還不只這些,開啟 Ant Design 控制檯,讓我有點崩潰的是,居然是不斷更換svg連結實現的,如果一直放在 Logo 上就會源源不斷的請求圖片,小圖示也會出現“閃爍”的情況

image-20220124235204747

這個請求量就有點驚人了。如果有負責 Ant Design 官網的小夥伴看到這裡,是不是可以優化一下呢?

最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤

相關文章