SVG超簡單實現豆瓣loading動畫

這段時間在豆瓣上看有什麼劇的時候,發現豆瓣的loading動畫還挺棒的。因此決定模仿着來寫一個。css

效果圖

我經過CSS3配合SVG來完成此次模仿豆瓣的loading動畫。沒用過SVG的也不用慌,我下面會寫出相應的屬性方便你去理解。由於這個真的超簡單。那麼咱們就直奔主題吧html

初始化svg

咱們須要先完成一個靜態的笑臉瀏覽器

始化SVG視圖的大小bash

<svg width="100" height="100"></svg>
複製代碼

我指定了一個寬高都爲100px的區域,width=」100」width=」100px」是等價的。svg

畫嘴巴

咱們把嘴巴給畫出來,在svg內先畫一個圓函數

<circle class="mouth" cx="50" cy="50" r="14"></circle>
複製代碼

cxcy 屬性定義圓點的 xy 座標。動畫

看到瀏覽器上面多了一個填充的黑色圓點spa

原型

接下來咱們給咱們的嘴巴加上css樣式3d

.mouth {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 44, 44;
    transform-origin: center;   /* transform動畫時以自身中心做爲基點 */
}
複製代碼

對應的屬性調試

css屬性 說明 此處
fill 填充顏色 none(不填充)
stroke 輪廓的顏色 #00B51D
stroke-width 輪廓的寬度 5
stroke-linecap 開放路徑兩端的形狀 round
stroke-dasharray 建立虛線 44, 44
transform-origin 旋轉元素的基點位置 center(自身中心)

這裏重點講一下stroke-dasharray,它的屬性值可爲none<dasharray>inherit

<dasharray>它是一個<length><percentage>數列,數與數之間用逗號或者空白隔開,指定短劃線和缺口的長度。

一個參數時: 實際上是表示虛線長度和每段虛線之間的間距
兩個參數或者多個參數時:一個表示長度,一個表示間距

  • stroke-dasharray = '10' 表示:虛線長10,間距10,而後重複 虛線長10,間距10
  • stroke-dasharray = '10, 5' 表示:虛線長10,間距5,而後重複 虛線長10,間距5
  • stroke-dasharray = '20, 10, 5' 表示:虛線長20,間距10,虛線長5,接着是間距20,虛線10,間距5,以後開始如此循環

根據圓的周長公式L=2πr,圓的半徑r=14,因此L=87.96452≈88,那麼咱們取虛線長度爲44,間距44作一條虛線,恰好就是圓周長的一半。

可見此時咱們的嘴巴部分已經完成了

原型

畫眼睛

接下來開始畫眼睛,我又畫了一個circle

<circle class="eye" cx="50" cy="50" r="14"></circle>
複製代碼

原型

咱們依然能夠經過stroke-dasharray來畫出一對眼睛

先把嘴巴註釋掉,避免影響咱們調試。

stroke-dasharray的虛線長度爲0的時,則能夠獲得無數個點狀的圓。根據上面圓的周長公式咱們能夠獲得周長爲88,那麼咱們每1/4個長度就爲22,此時咱們再把間距調整爲66。此時兩個點的垂直距離恰好爲90度

接下來咱們給咱們的眼睛加上css樣式

.eye {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 0, 66;
}
複製代碼

原型

爲了讓嘴巴對齊,咱們左旋轉45度,給eye加上transform屬性

transform-origin: center;
transform: rotate(-45deg);
複製代碼

原型

這樣子咱們就完成了眼睛

加動畫

通過我無數遍慢放(一幀一幀)的觀察豆瓣的加載動畫,終於找到了規律(哭)。

嘴巴動畫

加動畫效果,這也是最激動的一步,咱們先來看下嘴巴部分

原型

經過動畫咱們能夠看出嘴巴部分是旋轉了兩圈的,而且在旋轉第一圈的時候,兩邊的間距縮小爲1/4,在第二圈的時候,間距恢復爲1/2,且最後有一段的停留時間

根據最後的一段停留時間旋轉兩圈

咱們能夠經過transform完成,簡單

@keyframes mounthAni {
    80%, 100% {
        transform: rotate(720deg);
    }
}
複製代碼

第一圈的時候兩邊間距縮小爲1/4,也就是此時stroke-dasharray的值爲 44, 22,後續再恢復爲1/2

@keyframes mounthAni {
    40% {
        stroke-dasharray: 44, 22;   /* 間距改成1/4 */
    }
    80%, 100% {
        stroke-dasharray: 44, 44;   /* 間距恢復爲1/2 */
        transform: rotate(720deg);
    }
}
複製代碼

動畫的運行速度爲開始快,結束慢,因此咱們使用ease-out做爲貝塞爾曲線函數值

這樣嘴巴的動畫就完成了

眼睛動畫

原型

一樣的,經過動畫咱們能夠看出眼睛部分一樣是旋轉了兩圈,而且在旋轉第一圈的時候,兩邊的間距增大爲7/8,在第二圈的時候,間距恢復爲3/4,且最後有一段的停留時間

@keyframes eyeAni {
    40% {
        stroke-dasharray: 0, 77;    /* 間距改成7/8 */
    }
    80%, 100% {
        transform: rotate(675deg);  /* 間距恢復爲3/4 */
        stroke-dasharray: 0, 66;
    }
}
複製代碼

動畫的運行速度爲開始和結束慢,因此咱們使用ease-in-out做爲貝塞爾曲線函數值

至此咱們的眼睛動畫也就完成了

咱們把兩個動畫整合起來,這樣就完成了模仿豆瓣的loading動畫了,特簡單。

效果圖

源碼

html

<svg width="100" height="100">
    <circle class="mouth" cx="50" cy="50" r="14"></circle>
    <circle class="eye" cx="50" cy="50" r="14"></circle>
</svg>
複製代碼

css

.mouth {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 44, 44;
    transform-origin: center;   /* transform動畫時以自身中心做爲基點 */
    animation: mounthAni 2.3s ease-out infinite;
}

.eye {
    fill: none;
    stroke: #00B51D;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 0, 66;
    transform-origin: center;
    transform: rotate(-45deg);
    animation: eyeAni 2.3s ease-in-out infinite;
}

@keyframes mounthAni {
    40% {
        stroke-dasharray: 44, 22;   /* 間距改成1/4 */
    }
    80%, 100% {
        stroke-dasharray: 44, 44;   /* 間距恢復爲1/2 */
        transform: rotate(720deg);
    }
}

@keyframes eyeAni {
    40% {
        stroke-dasharray: 0, 77;    /* 間距改成7/8 */
    }
    80%, 100% {
        transform: rotate(675deg);  /* 間距恢復爲3/4 */
        stroke-dasharray: 0, 66;
    }
}
複製代碼

總結

CSS3動畫已足夠強大,可是若是要實現上面那種間距可變大變小的動畫效果,只用CSS的話我仍是沒有想到怎麼實現,若是各位有方法的話歡迎評論告訴我😀,因此使用了SVGCSS來完成,眼睛部分本來想過使用animateMotion來完成,奈何看了半天仍是不會用🤣,因此就想着只用CSS的動畫效果完成了此次的動畫,沒想到意外的簡單,因此把方法分享給你們。整個loading動畫都圍繞着stroke-dasharray展開,用到的SVG屬性真的是冰山一角,上面的內容若是有什麼錯誤的話還望各位多多指教。

相關文章
相關標籤/搜索