svg实现圆形进度条

213 阅读2分钟

zhuanlan.zhihu.com/p/662139481 这位作者写的非常好

<svg width="200" height="200">
  <circle 
    cx="100" 
    cy="100"
    r="95"
    fill="none" 
    stroke="blue" 
    stroke-width="10" />
</svg>

cx,cy:为圆形的中心点坐标x,y

r:为圆的半径

fill:圆形的填充色 只需要圆环设置透明色就好

strok: 圆环的颜色

stroke-width: 圆环的宽度

strokeDasharray:圆环的进度 太深奥了 我也说不明白 原作者写的很清楚 我套用了公式

也就是说要画一个圆形进度条 需要写一个svg 里面包两个circle 上面的circle 作为背景色不需要进度也就是不需要 strokeDasharray样式属性 作为进度的需要

为了完美适应容器尺寸,我们可以将半径 `r` 的值设置为容器宽度的一半减去 `stroke-width` 大小的一半,
这样做可以确保圆环不会因为溢出而被容器剪裁掉。
此处 r = 200 / 2 - 10 / 2,即 (200 - 10) / 2 = 95

1.需求中要用到第二进度条(一根进度条不够,要有两根,并且是重叠的,也就是第二进度条要超出第一个进度条才能看到)

2.并且要可以修改进度条背景色

饿了么ui里面不支持,所以自己手写了一个 看了下饿了么源码里面使用svg写的 但是有的又没看明白 所以就在网上搜了下svg写圆形进度条的方法

需求中涉及到可以动态改变宽高 切宽高不显示 也就是不一定是宽高相等的 data.area.x.value为宽度 data.area.y.value为高度 所以只能判断宽高中最小的数作为圆的计算半径参数 就有了(Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) 作为宽度

半径: ( 容器宽度 - 进度条宽度 - 2 ) / 2 多减了一个2是因为害怕圆形大小会溢出

下面是我的代码:因为有第二进度条所以就多写了一个circle

<svg :width="data.area.x.value" :height="data.area.y.value" class="circleSvg">
          <circle
            :cx="data.area.x.value / 2"
            :cy="data.area.y.value / 2"
            :r="((Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) - data.progressWidth.value - 2) / 2"
            :stroke-width="`${data.progressWidth.value}px`"
            :stroke="hex2Rgba(data.progressBgColor.value, data.progressBgColor.opacity) || '#cccccc'"
            fill="transparent"
          ></circle>
          <circle
            :cx="data.area.x.value / 2"
            :cy="data.area.y.value / 2"
            :r="((Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) - data.progressWidth.value - 2) / 2"
            :stroke-width="`${data.progressWidth.value}px`"
            :stroke="hex2Rgba(data.secondProgressColor.value, data.secondProgressColor.opacity) || '#addfe0'"
            fill="transparent"
            :style="{
              strokeDasharray: `${
                (((2 * 3.1415 * ((Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) - data.progressWidth.value)) / 2) *
                  data.ProgressTpye.secondaryProgress) /
                100
              },1000`,
              opacity: data.ProgressTpye.secondaryProgress
            }"
          ></circle>
          <circle
            :cx="data.area.x.value / 2"
            :cy="data.area.y.value / 2"
            :r="((Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) - data.progressWidth.value - 2) / 2"
            :stroke-width="`${data.progressWidth.value}px`"
            :stroke="hex2Rgba(data.progressColor.value, data.progressColor.opacity) || '#eda8a8'"
            fill="transparent"
            :style="{
              strokeDasharray: `${
                (((2 * 3.1415 * ((Number(data.area.x.value) < Number(data.area.y.value) ? data.area.x.value : data.area.y.value) - data.progressWidth.value)) / 2) *
                  data.ProgressTpye.currentProgress) /
                100
              },1000`,
              opacity: data.ProgressTpye.currentProgress
            }"
          ></circle>
        </svg>

/* SVG 容器 */
.progress-circle {
 transform: rotate(-90deg); // 让进度条从上方正中间开始 旋转放到svg上面的盒子 如果放到svg上旋转 有些情况会有问题比如绘制缩略图的时候会导致和进度条本身方向不符
}
.progress-circle > svg {
  display: flex;
  justify-items: center;
  align-items: center;
}
/* 进度条圆环 */
.progress-circle circle {
  stroke-linecap: round; // 让进度条的的边框是有圆角弧度的不是方的
  transition: stroke-dasharray 0.4s linear, stroke 0.3s; // 动画 进度增加看上去缓和一些
}

如果要用渐变色 svg不支持直接使用渐变色 需要用到特定的标签 zhuanlan.zhihu.com/p/515854742… zhuanlan.zhihu.com/p/590107236