今天看啥  ›  专栏  ›  YyzclYang

利用 svg 制作环形进度条

YyzclYang  · 掘金  ·  · 2019-10-06 14:28
阅读 16

利用 svg 制作环形进度条

前言

这两天做了个环形进度条的组件,之前用 css 做过,这次就打算尝试下用 svg 来做。

看一个进度条

01.jpg

它其实是由两部分组成的,第一部分是背景的灰色圆圈,第二部分是蓝色的圆弧。两部分叠加就组成了环形进度条。

svg 的代码也非常简单,如下所示:

<svg width="240" height="240" viewBox="0 0 200 200">
  <circle
    cx="100"
    cy="100"
    r="70"
    stroke-width="30"
    stroke="#E5E5E5"
    fill="none"
  ></circle>
  <circle
    cx="100"
    cy="100"
    r="70"
    stroke-width="30"
    stroke="#506DFE"
    fill="none"
    transform="matrix(0, -1, 1, 0, 0, 200)"
    stroke-dasharray="219 439"
  ></circle>
</svg>
复制代码

代码中的各个参数是什么意思呢?

02.jpg

第一部分的灰色圆圈很好理解,第二部分的圆弧就多了些参数,正是这些参数产生了圆弧的效果。

旋转

circle 圆圈的默认起始点是右边,那么要把它的起始点变成顶点,那就需要做一个旋转。

旋转参数有多种写法,第一种是利用 rorate 来实现。

如果需要以 (100, 100) 为中心点旋转 -90 度,那么参数为 transform="rotate(-90, 100, 100)"

第二种是利用矩阵来实现旋转,同样的旋转效果代码为 transform="matrix(0, -1, 1, 0, 0, 200)",矩阵具体该怎么写,可参考这篇文章

圆弧

circle 实现的是一个完整的圆圈,要实现圆弧效果该怎么做呢?

这里是利用的 stroke-dasharray 来实现的。

stroke-dasharraysvg 中表示描边的是虚线,它可以包含两个值,第一个值是虚线的宽度,第二个是虚线的间距,如果我们把虚线的宽度设置成圆弧的长度,间距设置为超过空白圆弧的长度即可实现圆弧效果。

比如说实现一个 50% 的圆弧,那么第一个值就为 50% * 2 * Math.PI * r,第二个值直接设置为 2 * Math.PI * r,这样不管怎么变,空白圆弧的长度是够的。

总结

就这样,通过一个背景色的圆圈加一个圆弧就组成了一个环形进度条。

至于还有一些颜色设置,线条的圆角/方角就不一一介绍了。

附上生成 transform 参数及 stroke-dasharray 的两个辅助函数。

  • 旋转矩阵
interface OriginCoordinate {
  x: number;
  y: number;
}

const rotateMatrixGenerator = (
  rotate: number,
  { x: currentOriginX, y: currentOriginY }: OriginCoordinate,
  { x: transformOriginX, y: transformOriginY }: OriginCoordinate
) => {
  const cos = Math.cos((rotate / 180) * Math.PI);
  const sin = Math.sin((rotate / 180) * Math.PI);

  return `matrix(${cos}, ${sin}, ${-sin}, ${cos}, ${transformOriginX -
    cos * currentOriginX +
    sin * currentOriginY}, ${transformOriginY -
    sin * currentOriginX -
    cos * currentOriginY})`;
};
复制代码
  • 圆弧
const arcGenerator = (
  radius: number,
  percentage: number,
  arcAngle: number = 360
) => {
  return `${percentage * radius * 2 * Math.PI * (arcAngle / 360)} ${radius *
    2 *
    Math.PI}`;
};
复制代码



原文地址:访问原文地址
快照地址: 访问文章快照