可线性渐变的环形进度条的实现探究

本文主要介绍基于 NutUI Vue3 的 circleProgress 组件的设计与实现原理,是一个圆环形的进度条组件,用来展示操作的当前进度,支持修改进度以及渐变色。环形进度条是很常用的一个组件,特别是在管理后台数据统计的页面上或是一些需要用户等待的任务。

实现效果

效果如下图

可线性渐变的环形进度条的实现探究_第1张图片

实现思路

首先我们来理一下我们的需求,我们需要一个圆形的可以改变进度,有动画的,可以支持渐变色的进度条

目前是有三种常见的实现方案:

  • CSS 实现

  • SVG 实现

  • Canvas 实现

而 SVG 又分为两种,一种是直接用 circle 实现,另外一种是用 path 来画出来。

然后我们来看下一些国内出名的组件库实现方式:

Antd Design Tdesign varlet Element UI vant
SVG Circle Circle Circle Path Path

Antd Design和TDesign,varlet 采用svg的Circle实现,但是小编个人觉得Antd Design的渐变色的开始和结束是有问题的,TDesign和varlet暂时不支持环形进度条线性渐变
Element UI和Vant 采用svg的Path实现,Vant是支持线性渐变的,而且不存在渐变色的开始和结束不对应问题,Element暂时不支持线性渐变

目前主流组件库的环形进度条基本上都是用svg绘出来的,因为实现思路简单,使用 SVG 画两个圆 一个圆作为底色,另一个圆作为进度展示,使用时候的问题也很少。NutUI也选择使用SVG来实现进度条。

下边详细介绍一下两种实现方式

circle实现

首先来说下 SVG 的 circle (Antd,Tdesign的实现方式),下边也会介绍到Antd的进度条线性渐变问题

首先第一步 我们先来画个最简单的圆

<svg height="100" width="100" x-mlns="http://www.w3.org/200/svg">
  <circle r="40" cx="50" cy="50" stroke="'red'" stroke-width="10" fill="none" />
</svg>

可线性渐变的环形进度条的实现探究_第2张图片

上边的属性我就不多介绍了 不了解的同学其实也可以读出来大概意思,r 是半径,cx,cy 为圆点位置,以及颜色和弧度的宽度。
这里可能有的同学要问了 这不是一个 circle 就可以实现嘛,可不要忘记了我们需要的效果,

那我们再来画一个不是100%进度的圆,如何画呢
这里就用到了 stroke-dasharray 属性,可以将图形的描边进行点状化,这里需要理解的是,点状化的点,其大小是可以设置的,并不真的就是那么一个·,可以变长或者变短。
所以如果 circle 的点的长度正好等于 circle边长,那么点看上去就是 circle 的边。
我们计算下圆环的周长就可以了,参数也就是弧长,极大值,极大值就是周长,弧长就是进度值。
可线性渐变的环形进度条的实现探究_第3张图片
大家应该也发现问题了,这样的话在不是100%进度的时候,部分弧度是没有颜色的,所以我们还需要一个底色。也就是另外一个circle

<svg>
  <circle
    r="40"
    cx="50"
    cy="50"
    stroke="#d9d9d9"
    stroke-width="10"
    fill="none"
  />
  />
  <circle
    r="40"
    cx="50"
    cy="50"
    stroke="red"
    stroke-width="10"
    stroke-dasharray="200,251"
    fill="none"
    stroke-linecap="round"
  />
</svg>

因为这里我们需要它从左边的中间位置开始,所以还需要加上旋转。
可线性渐变的环形进度条的实现探究_第4张图片

至于接下来就很简单了 让它动起来,那么如何动起来呢 动态改变 stroke-dasharray 的值就可以了,下方介绍path的时候会讲到如何改变。来讲一下遇到的小坑 ,就是我们在做渐变色的时候,会发现我们的渐变色并不是从我们的进度开始地方开始渐变的。
这里我们也可以看下Antd的环形进度条渐变,我用一个红到黑来给大家看一下。(Tdesign这里小编在在线编辑器里尝试了一下,线性渐变没有生效。)
可线性渐变的环形进度条的实现探究_第5张图片

这里小编个人觉得Antd的这个渐变也是不对的(仅代表个人想法),当然大家有别的想法也可以提出来一起探讨。

其实是因为线性渐变是从左往右的,并且上边为圆环加了旋转的原因,解决方法大家可以自行搜索引擎搜索一下,这里不多做阐述。

path实现

下边主要介绍一下用 pathVant,Element实现方法)实现吧 可以简单并完美的解决上边的渐变色对应不上(Element暂时不支持线性渐变)的问题。

circle 实现思路是一样的,画两个圆,一个用来表示底色,一个用来表示弧度,主要是我们如何来画一个圆呢

  1. 了解viewBox属性,在SVG标签中添加该属性,这个属性是用来设置画布的大小,但是大家注意,它是一个相对大小,会根据我们的父元素改变而动态适配。比如我们将其属性设置为 viewBox="0,0,100,100",其实它是将我们的整个画布的宽和高分为100份,其中SVG元素是在这个分割以后的画布上摆放展示。

我们不需要再关注 SVG 的宽高,它现在已经实现了自适应,会自动根据外层父元素的宽高进行
适配,我们最外层给用户一个 Props 来设置环形进度条的大小。

<div :style="{ height: radius * 2 + 'px', width: radius * 2 + 'px' }">
       <svg viewBox="0 0 100 100"></svg>
 </div>
  1. 了解path的d属性,既然我们要用path来画圆,那我们当然得熟悉一下的d属性来,它可以画出各种各样的线来。d 属性用来定义路径数据,我们首先来了解下我们需要用到的参数:
  M = moveto(M X,Y) :将画笔移动到指定的坐标位置

  A = elliptical Arc<

你可能感兴趣的:(NutUI,javascript,前端,ui,vue.js)