1. 程式人生 > >[SVG實戰]餅圖全面解析

[SVG實戰]餅圖全面解析

rotate code 處理 半徑 數學 偏移 空格 使用 clas

之前寫過一篇CSS3的餅圖全面解析,這次給大家分享一個SVG實現餅圖的全面解析。

既然是繪制餅圖,那麽顯然需要繪制圓形。

// 一個簡單的圓形,具有一定寬度的描邊。
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <circle r="30" cx="50" cy="50" fill="yellowgreen" stroke="#655" stroke-width="30" />
</svg>

描邊剛好是從半徑30的位置開始左右兩邊平均各分配15px的寬度,這樣整個圓形看起來就像是45px的半徑寬度。

於是,如果我們將描邊的寬度設置為半徑的兩倍,那麽整個圓都會被描邊所覆蓋。

接著利用stroke-dasharray這個屬性設置描邊的點劃線的圖案範式,也就是指定短劃線和缺口的長度。取值是一個數列,使用逗號或空格分開,依次表示短劃線的長度,缺口的長度。

// 設置描邊寬度為半徑的兩倍,同時指定stroke-dasharray屬性
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <circle r="25" cx="50" cy="50" fill="yellowgreen" stroke="#655" stroke-width
="50" stroke-dasharray="20 10"/> </svg>

此時,如果我們將第二個值(缺口的長度)設置為整個描邊的長度,那麽第一個值(短劃線的長度)就變的有意義了,可以用它來表示百分比。從而實現餅圖。

// 圓的半徑為25 周長2*PI*R=158 那麽stroke-dasharray的第二個值就設置為158
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <circle r="25" cx="50" cy="50" fill="yellowgreen" stroke
="#655" stroke-width="50" stroke-dasharray="16 158"/> </svg>

16/158剛好約等於10%,由實際效果圖也能看出來。

但是這裏有個小問題,那就是描邊都是從0度開始的,怎麽將起始點移動到圓的最上方呢?那就是利用變換,也就是rotate旋轉。將svg元素的世界坐標軸進行逆時針方向90度旋轉即可。

最後給circle這個元素加上一個CSS3動畫(當然也可以考慮使用SMIL動畫)就可以實現餅圖百分比從0到100的動畫效果了。

// stroke-dasharray屬性的第一個值從0變化到158
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <circle r="25" cx="50" cy="50" fill="yellowgreen" stroke="#655" stroke-width="50" stroke-dasharray="0 158"/>
</svg>
@keyframes fillup{
  to{
     stroke-dasharray: 158 158;      
  }  
}
svg{
  transform: rotate(-90deg);
  background: yellowgreen;
  border-radius: 50%;
}
circle{
animation: fillup 5s linear infinite;
}

直接看效果圖即可:

拔高篇

如何給餅圖添加第三種顏色呢?

這時候就要派出另外一個stroke系列屬性: stroke-dashoffset

stroke-dashoffset這個屬性是用來指定stroke-dasharray屬性中短劃線的偏移量。

先上一個簡單的小案例

<svg width="100px" height="100px" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#123456" stroke="#ccc" stroke-width="0.5"/>
    <line x1="0" y1="50" x2="100" y2="50" stroke="#fff" stroke-width="1" stroke-dasharray="10 5" />
</svg>
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#123456" stroke="#ccc" stroke-width="0.5"/>
    <line x1="0" y1="50" x2="100" y2="50" stroke="#fff" stroke-width="1" stroke-dasharray="10 5" stroke-dashoffset="-5" />
</svg>
<svg width="100px" height="100px" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#123456" stroke="#ccc" stroke-width="0.5"/>
    <line x1="0" y1="50" x2="100" y2="50" stroke="#fff" stroke-width="1" stroke-dasharray="10 5" stroke-dashoffset="5" />
</svg>

效果圖如下,可見當stroke-dashoffset設置為負數時,點劃線的位置會後移,而設置為正數時,點劃線的位置會前移。

那麽利用這個特性,我們完全可以在svg中繪制多個圓形,每個圓形根據各自的百分比數設置對應的stroke-dasharray屬性的第一個屬性值。而將stroke-dashoffset設置為前面已有百分比的數值總和的負數。還需要註意一點的就是後面覆蓋的圓必須設置fill=none 其實第一個圓也可以不用設置fill顏色,因為整個畫布已經fill了一種顏色。

<svg width="100px" height="100px" viewBox="0 0 100 100">
    <circle r="25" cx="50" cy="50" fill="none" stroke="#f00" stroke-width="50" stroke-dasharray="16 158" />
    <circle r="25" cx="50" cy="50" fill="none" stroke="#0f0" stroke-width="50" stroke-dasharray="48 158" stroke-dashoffset="-16"/>
    <circle r="25" cx="50" cy="50" fill="none" stroke="#00f" stroke-width="50" stroke-dasharray="79 158" stroke-dashoffset="-64"/>
</svg>

總結篇

其實實現餅圖效果的方案無非就是CSS3,Canvas,SVG。如果是報表應用,那完全可以用Canvas來實現,而且現成的CanvasJS庫也非常多: chart.js, echart.js, c3.js d3.js等等。

而如果是顯示餅圖動畫loading效果,那可以用SVG來簡單處理,甚至很容易給餅圖添加多種顏色。CSS3實現餅圖loading效果則還需要一定的數學計算。當然SVG也有現成的庫,也可以用來繪制報表應用。

[SVG實戰]餅圖全面解析