iT邦幫忙

DAY 23
3

SVG 30 天 ~ 就要醬玩系列 第 23

Day23 - SVG + CSS 製作 Material Design 進度條

這是一個利用 CSS 與 SVG 所做出來的進度條,仿照 Google Material Design 的設計風格設計,雖然 Google 有提供一系列的扁平風格樣式,但是由於技術尚未完全成熟,沒有相關的程式可以參考和套用,就自己寫了一個類似的,雖然還沒有模擬到百分之百,但已經是百分之八十接近了,分享一下。( oxxostudio.tw 同步發表:Material Design - Progress and Activity )

我所做的 Progress and Activity 結構其實很簡單,就是使用 SVG 內部的 Circle 進行虛線的長度和間距變換,然後外層的 SVG 進行 360 度的旋轉,再搭配另外一個 SVG Circle 就可以做出頗炫的動態效果,整個效果完全不需要用到 JS, 只需要撰寫 CSS 就完成囉!

首先看到 SVG 的結構,第一個 SVG 名為 loading-bg-red ,內容的 Circle 是背景的大圈圈,因此它的背景是半透明的 rgba(255,100,120,.2),因為我是使用虛線的外框 ( stroke ),至於為什麼 stroke-width設為 0 呢?因為一開始是沒有大圈圈的,所以設為 0,再使用 CSS 進行漸變,再來看到第二個 SVG,就是內容旋轉的進度條,最重要的是 stroke-dasharray和 stroke-dashoffset兩個屬性,主要掌管了這個虛線的長度以及虛線要跑去哪裡。 ( 可以參考我之前的 SVG 研究之路 (6) - stroke 邊框 )

<svg class="loading-bg-red" width="100" height="100" x="0" y="0" style="position:absolute; top:0; left:0;">
    <circle cx="50" cy="50" r="25" stroke="rgba(255,100,120,.2)" stroke-width="0" fill="none" stroke-dasharray="156,156" stroke-dashoffset="0" stroke-linecap="round"></circle>
</svg>

<svg width="100" height="100" class="loading-circle loading-red" x="100" y="100" style="position:absolute; top:0; left:0;">
    <circle cx="50" cy="50" r="25" stroke="#f99" stroke-width="1" fill="none" stroke-dasharray="104,156" stroke-linecap="round" stroke-dashoffset="-52"></circle>
</svg>

知道了 SVG 的結構,再來就看看要如何做出讓虛線一長一短的效果,首先要注意就是虛線的長度,因為要一長一短,起點和終點的位置要相同,所以我們可以用一個簡單的規則來設計相關的 CSS,規則就是如果虛線最長的長度是圓周的一半,則必須使用 2x2=4 也就是四個 CSS 來描述四段虛線,若長度為 2/3,則必須使用 2x3=6 六段 CSS 來描述六段虛線,同理,若為 3/4,就必須使用八段 CSS,至於為什麼要這麼多段呢?因為一段為收合,一段為延長,每段的虛線起始點都不同,所以必須這麼進行,也因此盡量讓虛線長度為 1/2 或 2/3 或 3/4,不然大概會寫 CSS 寫到天荒地老吧!以下列出我寫的虛線 ( 2/3 長度 ) 的 CSS。

.loading-circle circle{ 
  -webkit-animation:c1_2 9s linear infinite,c1_3 4.5s infinite; 
  -moz-animation:c1_2 9s linear infinite,c1_3 4.5s infinite; 
  animation:c1_2 9s linear infinite,c1_3 4.5s infinite; 
}

/*控制粗細*/
@-webkit-keyframes c1_2{
  0%{
    stroke-width:0;
  }
  10%{
    stroke-width:8;  
  }
  75%{
    stroke-width:8;  
  }
  90%{
    stroke-width:0;  
  }
  100%{
    stroke-width:0;  
  }
}

/*控制段落*/
@-webkit-keyframes c1_3{
  /*第一段*/
  0%{
    stroke-dasharray:104,156;
    stroke-dashoffset:-52;
  }
  16%{
    stroke-dasharray:1,156;
    stroke-dashoffset:-52;
  }
  /*第二段*/
  16.01%{
    stroke-dasharray:1,156;
    stroke-dashoffset:-208;
  }
  33%{
    stroke-dasharray:104,52;
    stroke-dashoffset:-104;
  }
  /*第三段*/
  33.01%{
    stroke-dasharray:104,52;
    stroke-dashoffset:-104;
  }
  49%{
    stroke-dasharray:1,156;
    stroke-dashoffset:-104;
  }
  /*第四段*/
  49.01%{
    stroke-dasharray:1,156;
    stroke-dashoffset:52;
  }
  66%{
    stroke-dasharray:104,52;
    stroke-dashoffset:156;
  }
  /*第五段*/
  66.01%{
    stroke-dasharray:104,52;
    stroke-dashoffset:156;
  }
  82%{
    stroke-dasharray:1,156;
    stroke-dashoffset:156;
  }
  /*第六段*/
  82.01%{
    stroke-dasharray:1,156;
    stroke-dashoffset:156;
  }
  99.99%{
    stroke-dasharray:104,52;
    stroke-dashoffset:256;
  }
}

如果還是對於分成六段有疑問,可以參考下圖,主要就是要將這三個圈圈組合起來,每個圈圈會收會放,換成這樣子思考,就會必較簡單。

了解了整體的運作模式之後,最後一個步驟就是讓整個 SVG 進行旋轉,因此加上旋轉的 CSS 動畫,就可以做出相當不錯的特效囉!

@-webkit-keyframes c1_1{
  0%,100%{
    -webkit-transform:rotate(0deg);
  }
  100%{
    -webkit-transform:rotate(-360deg);
  }
}

完整的程式碼可以參考 jsbin 範例連結


上一篇
Day22 - 寫 jquery 產生 SVG 圓餅圖
下一篇
Day24 - 初探 SVG filter
系列文
SVG 30 天 ~ 就要醬玩31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
mis2000lab
iT邦好手 1 級 ‧ 2014-10-15 13:33:03

大師,您真的太厲害了,要不要出一本書?

因為有書在手邊,要查詢也很方便(算是解救眾生), thanks.

0
oxxo
iT邦研究生 1 級 ‧ 2014-10-15 13:47:28

mis2000lab 大大說的是... 不過我稱不上大師啦~ ^^|||
您的出版品豐富又精彩,望塵莫及呀~

私底下跟您請教 ^_^

我要留言

立即登入留言