用SVG实现进度环

3,059 阅读5分钟

需求

    

主要知识点

参考:developer.mozilla.org/zh-CN/docs/…

1.<path>元素是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状 

2.<path> 属性d一个点集数列以及其它关于如何绘制路径的信息(其值为path命令信息)

2.path命令 M(Move to它需要两个参数,分别是需要移动到的点的x轴和y轴的坐标)、m(也是Move to它需要两个参数,分别是相对于当前位置需要在X轴上移动距离、相对于当前位置需要在Y轴上移动的距离),path的小写英文字母命令中的位置都代表相对位置。

3.path命令 A(弧线命令,弧形可以视为圆形或椭圆形的一部分),

A(rx ry , x-axis-rotation, large-arc-flag, sweep-flag ,x y)

rx:x轴半径

ry:y轴半径

x-axis-rotation:x轴旋转的角度(顺时针为正)

large-arc-flag:弧线大于还是小于180度, 0表示小角弧度,1 表示大角弧度

sweep-flag:弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧

x:弧度的x终点

Y:弧度的y终点

(⊙_⊙)?为什么需要这么多参数来画弧线呢 可以参考:

developer.mozilla.org/zh-CN/docs/…

4.stroke-dasharray:可控制用来描边的点划线的图案范式 (用来画虚线)

5.stroke-dashoffset:属性指定了dash模式到路径开始的距离

(其中主要利用4、5知识点来显示圆环上的彩色进度 ^_^)

6viewBox属性的值是一个包含4个参数的列表 min-x, min-y, width and height, 以空格或者逗号分隔开, 在用户空间中指定一个矩形区域映射到给定的元素;例:

viewBox="0 0 100 100"

相当于,假设在100*100的范围内绘制图案,所有的大小都是相对于 100*100来说的,如果此时svg实际的大小是200*200,则整个图案中的长度单位其实会是原来的2倍。

主要实现步骤

1.画一个盛满整个容器的圆环

<div class="wrap" >
    <svg viewBox="0 0 100 100">        
        <path 
            stroke-width="10" 
            fill="none"          
            stroke="blue"          
            d="
                M 5 50  
                A 45 45, 0, 0, 1, 95 50
                A 45 45, 0, 0, 1, 5 50
            "        
        />      
    </svg>    
</div>

 <style>    
    .wrap{      
        width:300px;      
        height:300px;      
        border:1px solid pink;    
    }  
</style>

svg的实际大小由svg标签或者外部容器的大小决定;用很粗的线画圆就变成了圆环啦~由于线宽(strokeWidth) 也是占用了位置的,所以如果要画一个最大的圆,半径 radius = (width-strokeWidth)/2 得到 45,这里的radius指的是圆心到线宽中间的距离

首先将画笔移动到坐标(5,50)M 5 50 然后给出一个画弧线命令 

A 45 45, 0, 0, 1, 95 50 // 画出了一个上半圆

然后再给出一个画弧线命令 

A 45 45, 0, 0, 1, 5 50 // 下半圆好了,圆了


2.在原有的圆环上显示进度环

实现思路增加一个 <path>,覆盖在原来的圆环上,然后通过stroke-dasharray和stroke-dashoffset来实现进度条的效果。

 <div class="wrap" >
      <svg viewBox="0 0 100 100">       
        <path           
            stroke-width="10"          
            fill="none"          
            stroke="blue"          
            d="
                M 5 50             
                A 45 45, 0, 0, 1, 95 50            
                A 45 45, 0, 0, 1, 5 50          
            "        
        />        
        <path           
            stroke-width="10"          
            fill="none"          
            stroke="red"          
            d="
                M 5 50             
                A 45 45, 0, 0, 1, 95 50            
                A 45 45, 0, 0, 1, 5 50          
            "        
        />      
       </svg>    
</div>

这个时候是这样的: 蓝圈圈被红圈圈压在下面啦!


好!怎么让红圈圈只显示一部分呢??接下来我要简单介绍一下stroke-dasharray和stroke-dasharray

我们先来试试用stroke-dasharray画一条虚线从坐标(0,20)(100,20)

5px的实线3px的空白来显示这条虚线:

<path stroke-dasharray="5,3"  d="M0 20 L100 20"  stroke="red"/>


接下来我们来看看stroke-dashoffset的作用, 虚线偏移

 <path 
    stroke-dashoffset="2" 
    stroke-dasharray="5,3" 
    d="M0 20 L100 20" stroke="red"
/>

整根虚线被活生生的像起点方向拖动了 2个单位!


那么我们是不是可以把画一个一圈红一圈透明的圈圈缠绕起来的东西,然后朝起点方向偏移呢

先来算一下周长 Math.PI * 2 * radius  

stroke-dasharray="Math.PI * 2 * 45"

如果要让进度条占整个圆环的80%,那么就要向起点位置拖动周长的 20%

stroke-dashoffset="Math.PI * 2 * 45*.2"

    <div class="wrap" >      
        <svg viewBox="0 0 100 100">        
            <path           
                stroke-width="10"          
                fill="none"          
                stroke="blue"          
                d="
                    M 5 50             
                    A 45 45, 0, 0, 1, 95 50            
                    A 45 45, 0, 0, 1, 5 50          
                "        
            />       
            <path           
                stroke-width="10"          
                fill="none"          
                stroke="red"          
                d="
                    M 5 50             
                    A 45 45, 0, 0, 1, 95 50            
                    A 45 45, 0, 0, 1, 5 50          
                "          
                stroke-dasharray ="282"          
                stroke-dashoffset="56.4"       
            />      
        </svg>    
    </div>

如果想要圆角效果 stroke-linecap="round"


基本上效果已经达到了,如果想要有动的效果的话可以通过transition 添加动画。

半圆的进度条实现原理是一样的只画半个圆就可以啦~~,可以封装成灵活的组件来使用,这里只记录主要的实现步骤。

前端菜鸟第一次写文章,旨在分享记录学习的过程,如果有哪里写的不够好欢迎指正,(*╹▽╹*)