最近用了一个多月的时间完成了一个数据可视化大屏,大概的效果是这个样子的,当然这只是三屏中的其中一屏,我会用几篇文章分别介绍各个点的实现方式和一些相应的知识点。
首先这次会介绍右下角的间断圆环图的实现,圆环图会根据数据多少,进行相应的变化。并且,圆环的内容是间断的,且带有从浅到深的渐变。
实现初尝
看到图形,我们首先会想到它跟圆环的结构稍有类似,那我们可以按照实现圆环的思路可以通过以下方式实现,使用左右两个半圆,并控制其遮罩的旋转,来控制进度,类似以下这种:
然后,我们可以将两边的半圆,换做我们的底图,进行拼接。这时候我们会发现,如果想要遮罩完全遮住底图的话,我们的整个图形就没办法做成透明的了。尴尬,只能换思路。
快乐的使用SVG
头痛之余,借鉴了一下网上的其他圆环的解决方案,发现了一篇张鑫旭大神的文章,很巧妙的用stroke-dasharray实现了圆环进度。
大概原理如下:
stroke-dasharray在SVG中表示描边是虚线,两个值,第一个是虚线的宽度,第二个是虚线之间的间距。所以,我们只要让这根线,保持只有一段实线+一段虚线就行了,也就是
实线长度(对应数据) + 虚线长度 = 圆环周长
代码如下(直接):
<svg width="440" height="440" viewbox="0 0 440 440">
<circle cx="220" cy="220" r="170" stroke-width="50" stroke="#D1D3D7" fill="none"></circle>
<circle cx="220" cy="220" r="170" stroke-width="50" stroke="#00A5E0" fill="none" transform="matrix(0,-1,1,0,0,440)" stroke-dasharray="0 1069"></circle>
</svg>
朝最终效果进发
按照前面的思路,实现一个间断圆环的思路也就顺理成章的出来了。我们可以把整个圆环分成N份,每份包含一段实线,一段虚线。例如我们要实现80%的圆环,对应的stroke-dasharray就是:
const dashItemLength = (周长 / (N * 2))
// 向上取整 保证有整数个数据
const dashItemNum = Math.ceil(N * 0.8)
// 这里 实线虚线的长度是相同的, 减1 是预留出最后的空白
const dashLine = `${dashItemLength} ${dashItemLength},`.repeat(dashItemNum - 1)
// 最后需要将最后的虚线长度进行补齐
const restLength = 周长 - (dashItemLength * dashItemNum)
const dashLineArray = dashLine.split(',')
dashLineArray.push(`${dashItemLength} ${restLength}`)
const result = dashLineArray.join(' ')
大概效果就是这样子:
最终渐变
我们会发现,圆环的渐变不是简单的线性渐变,它是环绕着圆环进行的。这个时候,把里面的圆环直接加上渐变是达不到效果的,这时候,我们需要把整个圆环拆成两份,例如我想要从黄色渐变到红色,那就是,右边是黄色到中间色,左边是中间色到红色。 对应的虚线计算,也需要拆成两部分进行了。
具体代码就不在这里赘述,关键要实现以下几个步骤:
- 拆分成左右两个圆环
- 如果数值小于50%,则左侧全部为虚线,右边按照正常计算补齐
- 如果数值多余50%,则右侧全部为虚实线,左边按照正常补齐
- 需要考虑每个单位的宽度,使50%的时候,单元正好卡在虚线中间
最终效果:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。