前言
最近项目中有一个页面需要显示一个带有百分比的圆环,效果如下:
我在网上找了些资料后发现很多人都是用SVG实现的
实现步骤
最开始,我其实只找到了这么个demo,它只是实现了圆环的基本效果:
可我我要的圆角加渐变怎么办呢?于是又找找找,发现了两个重要属性能实现,圆角是靠stroke-linecap属性设为round就可以了,颜色渐变就负责一些了,直接上代码吧:
<defs>
<linearGradient id='svg_1' x1='0%' y1='0%' x2='100%' y2='64.9%'>
<stop offset='0%' stop-color='#f8cb9c' />
<stop offset='50%' stop-color='#ef9383' />
<stop offset='100%' stop-color='#ea7575' />
</linearGradient>
</defs>
<circle
cx='90'
cy='90'
r='80'
strokeWidth='12'
stroke='url(#svg_1)'
fill='none'
stroke-linecap='round'
transform='matrix(0,-1,1,0,0,180)'
strokeDasharray={this.getRingPercent(resultObj.score, 80)}
></circle>
感觉有点像css的·keyframes`有木有,通过设置几个节点的颜色值从而达到一个渐变的效果。
最后总体说一些实现思路,实际上就是通过两个circle标签,一个现实的是底色的环,一个是变化的环,而这个根据数值变化的环主要是靠stroke-dasharray属性实现的:
stroke-dasharray 的两个值,一个表示虚线的长度,另一个表示虚线与虚线之间的间距,而间距之间是一片空白,所以图形从圆变成了圆弧。然而这好像和我们想象中的有点不一样,我们希望它是从右上方开始的。所以我们需要转换一下坐标系。
所以stroke-dasharray第一个值就是你要展示的圆弧长度,而第二个值就是圆弧的周长,这个都是可以换算出来的。
用react实现的完整代码如下:
<svg width='180' height='180' viewBox='0 0 180 180'>
<defs>
<linearGradient id='svg_1' x1='0%' y1='0%' x2='100%' y2='64.9%'>
<stop offset='0%' stop-color='#f8cb9c' />
<stop offset='50%' stop-color='#ef9383' />
<stop offset='100%' stop-color='#ea7575' />
</linearGradient>
</defs>
<circle
cx='90'
cy='90'
r='80'
strokeWidth='12'
stroke='#3e2eae'
fill='none'
></circle>
<circle
cx='90'
cy='90'
r='80'
strokeWidth='12'
stroke='url(#svg_1)'
fill='none'
stroke-linecap='round'
transform='matrix(0,-1,1,0,0,180)'
strokeDasharray={this.getRingPercent(resultObj.score, 80)}
></circle>
</svg>
// 计算圆环长度数据
getRingPercent = (percent, r) => {
let perimeter = Math.PI * 2 * r; //周长
return (percent / 100) * perimeter + ' ' + perimeter;
};
目前实现的最终效果如下:
总结
其实这只是用SVG实现的一个很小的例子,后来无意中翻看像F2这种图形库时发现已经有现成的实现了,该是怪自己孤陋寡闻啊,哈哈,所以我相当于造了一个简单的轮子吧,毕竟我这个项目也只需要这个一个小图形,就引以整个库对性能也不好,他们那些库也无非是用SVG或者convas实现的,嗯,也只能这样安慰自己了,哈哈。
还是希望有机会多用用SVG和canvas吧,觉得这种矢量绘图还蛮有意思的,目前对SVG的api了解还不是很多,相当于照葫芦画瓢,用的多了对一些核心API理解多了应该会更得心应手一些!