8
最近用了一个多月的时间完成了一个数据可视化大屏,大概的效果是这个样子的,当然这只是三屏中的其中一屏,我会用几篇文章分别介绍各个点的实现方式和一些相应的知识点。

图片描述

首先这次会介绍右下角的间断圆环图的实现,圆环图会根据数据多少,进行相应的变化。并且,圆环的内容是间断的,且带有从浅到深的渐变。

实现初尝

看到图形,我们首先会想到它跟圆环的结构稍有类似,那我们可以按照实现圆环的思路可以通过以下方式实现,使用左右两个半圆,并控制其遮罩的旋转,来控制进度,类似以下这种:

clipboard.png

然后,我们可以将两边的半圆,换做我们的底图,进行拼接。这时候我们会发现,如果想要遮罩完全遮住底图的话,我们的整个图形就没办法做成透明的了。尴尬,只能换思路。

快乐的使用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(' ')

大概效果就是这样子:

clipboard.png

最终渐变

我们会发现,圆环的渐变不是简单的线性渐变,它是环绕着圆环进行的。这个时候,把里面的圆环直接加上渐变是达不到效果的,这时候,我们需要把整个圆环拆成两份,例如我想要从黄色渐变到红色,那就是,右边是黄色到中间色,左边是中间色到红色。 对应的虚线计算,也需要拆成两部分进行了。

具体代码就不在这里赘述,关键要实现以下几个步骤:

  1. 拆分成左右两个圆环
  2. 如果数值小于50%,则左侧全部为虚线,右边按照正常计算补齐
  3. 如果数值多余50%,则右侧全部为虚实线,左边按照正常补齐
  4. 需要考虑每个单位的宽度,使50%的时候,单元正好卡在虚线中间

最终效果:

clipboard.png


Athon
1.7k 声望1.1k 粉丝