會動的圓形進度條

本範例使用SVG處理圖形,並搭配使用stroke-dasharraystroke-dashoffset讓圖形能夠動態增長
注意本範例僅能適用在stroke類圖形,如果UI設計師把圖形轉成path的話,它就不適用了

stroke-dasharray屬性介紹

stroke-dasharray描述實線與虛線的配置,用法如下

stroke-dasharray: 實線值 虛線值

實線值與虛線值的單位不是px也不是pt
他的單位會跟viewbox的設定一起跑

svg(viewbox="-50 -50 100 100")
 line(x1=-50 y1=0 x2=50 y2=0)
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 line
  stroke: #000
  stroke-dasharray: 10 20

本例viewbox的設定值為-50 -50 100 100,即表示x軸起點值為-50,且長度為100,因此x軸的終點值為50

stroke-dasharray: 10 20的指定下,設定實線(黑線)為10,虛線為20
所以整個線段的虛實分佈為

-50-40實線段
-40-20虛線段
-20-10實線段
-1010虛線段
1020實線段
2040實線段
4050實線段

上述範例中viewbox的長度設定為100,所以整個實線/虛線可以用的總額就是100
寫成stroke-dasharray: 0 100的話,線就會不見(全都是虛線)
寫成stroke-dasharray: 100 0的話,就會看到一條全黑的實線(全都是實線)

補充:stroke-dasharray的多層次指定

stroke-dasharray可以指定多個值,一樣都是奇數值放實線長度,偶數值放虛線的長度描述
只要viewbox的長度不夠他走完,它就會回到最前面輪迴
前例的輪迴是2 base會比較單純,多層次指定的輪迴的虛實設定就會更複雜
(本章動態圓形進度條只需要用到2個值就可以了)

svg(viewbox="-50 -50 100 100")
 line(x1=-50 y1=0 x2=50 y2=0)
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 line
  stroke: #000
  stroke-dasharray: 10 15 20 25
位置虛線/實線段stroke-dasharray線段輪迴
-50-40實線段10
-40-25虛線段15
-25-5實線段20
-520虛線段25
2030實線段10
3045虛線段15
4550實線段20
這裡沒走完所以被卡掉
只剩短短一段而已

stroke-dashoffset屬性介紹

stroke-dashoffset提供開始位置偏移的效果
其實就是更動x1的數值,如果是stroke-dashoffset: 10的話x1的數值就會比原本的還要在-10

舉例來說

svg(viewbox="-50 -50 100 100")
 line(x1=-50 y1=0 x2=50 y2=0)
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 line
  stroke: #000
  stroke-dasharray: 100 100
  stroke-dashoffset: 10

這個範例中可以看到線段整個往左邊偏移了10,但是他其實也就是等於這個意思

svg(viewbox="-50 -50 100 100")
 line(x1=-60 y1=0 x2=50 y2=0)
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 line
  stroke: #000
  stroke-dasharray: 100 100
  // stroke-dashoffset: 10

圓形的stroke:百分比進度條

理解上述stoke-dasharraystroke-dashoffset原理之後,我們來看看圓形的版本要怎麼做

首先,普通的畫一個圓

svg(viewbox="-50 -50 100 100")
 circle(cx=0 cy=0 r=40)
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 circle
  fill: none
  stroke: teal

接著,再用stroke-dasharray讓這個圓具有進度條的感覺(嘗試畫75%的圓)

svg
 width: 300px
 height: 300px
 border: 1px solid #000
 circle
  fill: none
  stroke: teal
  stroke-dasharray: 188.4 62.8

圓周長的算法為

半徑(r)×2×3.14

上述範例的半徑r40,所以總圓周長為40×2×3.14251.2
再往下規劃實線/虛線的分配,實線線段要配給75%,虛線線段要配給25%,所以

  • 實線長度:251.2×75%=188.4
  • 虛線長度:251.2×25%=62.8

雖然成功畫出了75%的實線段與25%的虛線段,但是…位置看起來不像一個進度條
這是因為,<circle>的起始點是位於90deg的位置,也就是圓形的右方
然後再順時鐘往前畫出去

順時鐘這個方向是對的,但是90deg這個起點不理想
所以要再透過stroke-dashoffset偏移起始點,讓起始點變成0deg

svg
 width: 300px
 height: 300px
 border: 1px solid #000
 circle
  fill: none
  stroke: teal
  stroke-dasharray: 188.4 62.8
  stroke-dashoffset: 62.8

stroke-dashoffset的值也是以圓周長來算,由於要偏移1/4的圓周長的距離,所以給定總長度251.225%,也就是62.8的偏移量

這樣就是我們所熟悉的圓形進度條了!

接下來來透過stroke-dasharrayanimation實作動態
動態的技巧是:讓實線的值從0188.4,視覺上就能做出圓形長出來的效果了

svg(viewbox="-50 -50 100 100")
 circle(cx=0 cy=0 r=40)
 text(x=0 y=0) 75%
svg
 width: 300px
 height: 300px
 border: 1px solid #000
 circle
  fill: none
  stroke: teal
  stroke-dashoffset: 62.8
  animation: mycircle 3s infinite
 text
  fill: teal
  dominant-baseline: middle
  text-anchor: middle
  
 @keyframes mycircle
  0%
   stroke-dasharray: 0 251.2
  100%
   stroke-dasharray: 188.4 62.8