使用SVG制作进度条

发布于 大漠

进度条是我们在Web中经常看到的一种效果,常见的进度条有水平横条和径向圆形的进度条。今天我们来看看怎么使用SVG来实现进度条的效果。使用SVG可以很容易的实现,也易于理解,最主要是使用SVG实现的进度条具有良好的跨浏览器,并且能根据浏览器屏幕尺寸很好的显示。

基础

在具体制作之前,有一些简单的概念要了解一下,这是制作进度条的一些基础。

  • 水平进度条,是一条直线,使用SVG的<line>元素可以绘制
  • 圆形进度条,是一个环形,使用SVG的<circle>元素可以绘制
  • 通过fill:none设置线条无填充色,使用stroke-width来设置进度条的粗细

使用stroke-width设置进度条粗细,水平进度条相对而言较主简单,直接设置就能指定进度条的高度,对于其长度通过(x1,y1)(x2,y2)来确定。对于圆形进度条,同样需要使用fill:none让圆形不填充任何颜色,stroke-width设置圆形的粗细,只是其值是圆周长的十分之一。

通过stroke-width和圆的周长,我们可以计算出圆形的半径。比如我们圆形的外周长是120,同时stroke-width的值是12。这样我们就可以计算出圆形半径:

(120 / 2) - (12 / 2) = 54

SVG代码很简单:

<svg width="200" height="200" viewBox="0 0 200 200">
    <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" />
    <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" />
</svg>

这个时候你看到的效果如下:

制作进度条

事实上,我们所看到的进度条都是有另一个颜色来表示进度的,而上面我们看到的只是进度条的背景色。也就是说,我们需要再绘制一个<line><circle>元素,其坐标参数,进度条粗细等参数都一样,唯一不同的是,线条的颜色要不一样。

通过《SVG的图层和渲染顺序》和《优雅的轮廓与 SVG paint-order》学习,了解了SVG中绘制过程有自己的基本原则:

解析顺序和绘制顺序一致,都要遵守XML中元素的位置排列。SVG中元素在XML中有固定的排列顺序,浏览器渲染时会遵守这个顺序,绘制时也同样会遵守这个顺序。也就是说先出现的元素会出现在绘制的底层,而后出现的元素会绘制在顶层,如果元素间的位置有重叠,则会后绘制的元素会盖住先绘制的元素。

了解了这一种,那就好办了。依次在<line>后面再绘制一个<line>,并把它的stroke设置为其他颜色,比如orange。同样的在<circle>之后再绘制一个<circle>,同样把stroke设置为orange

<svg width="200" height="200" viewBox="0 0 200 200">
    <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" />
    <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" />
    <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" />
    <circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" />
</svg>

你将看到的效果现在变成这样了,橙色的覆盖了灰色的:

改变进度条位置

上面看到的效果就是进度条100%的位置,但我们很多时候不是100%,而是其他的位置,那么上面的效果就不是我们所需要的了。我们需要一些方法来处理不同进度时,橙色的进度位置。那怎么做呢?

如果你阅读了前面整理的:

我想你肯定会想到SVG的stroke-dasharraystroke-dashoffset。是的,就是这两个属性能轻易的帮助我们要达到我们想要的效果。其技术关键点:

  • 如果stroke-dasharraystroke-dashoffset设置的值都是路径(line的长度,circle的周长),那么橙色的linecircle将看不到,这个时候就是进度条0%的状态,当stroke-dashoffset加到0的位置时,这个时候就是进度条100%的状态。言外之意,改变stroke-dashoffset的值,就能得到进度条0%~100%之间的状态
  • 通过.getTotalLength()获取对应图形的长度。

比如:

document.querySelectorAll('line')[1].getTotalLength()   // => 100
document.querySelectorAll('circle')[1].getTotalLength() // => 338.7438659667969

这就好办了,在橙色的linecircle上设置stroke-dasharraystroke-dashoffset值:

<svg width="200" height="200" viewBox="0 0 200 200">
    <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" />
    <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" stroke-dasharray="100" stroke-dashoffset="100" />
    <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" />
    <circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" stroke-dasharray="339" stroke-dashoffset="339" />
</svg>

这样一来,橙色的就看不到了:

为了更易于理解,在上面的基础上做一下简单的修改:

上面的效果相对而言较为简单。如果你使用SVG的其他一些特性,比如渐变,甚至是将linecircle换成path。这样一来,要整成什么样形状的进度条都OK,也简单。比如下面这个示例:

总结

今天主要介绍了怎么使用SVG来制作水平和圆形的进度条,甚至怎么制作任意思形状的进度条。制作原理并不复杂,我想你要是阅读到这里,以及阅读前面的内容,你应该非常的清楚。但话说回来,现在的进度条效果还很粗陋,但并不要紧,如果你感兴趣的话,请关注后续的更新,下一次咱们来看看怎么用Vue来把今天这两个进度条封装成对应的组件,并且将这个进度条打磨的更精美。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/svg/create-progress-bar-with-svg.html2019 Air Vapormax Flair