[SVG实战]饼图全面解析

之前写过一篇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也有现成的库,也可以用来绘制报表应用。

posted @ 2017-07-30 00:53  小碎石  阅读(3566)  评论(0编辑  收藏  举报