SVG探索(一):借助SVG实现一个环形进度条效果
前言
首先,SVG 是什么?
SVG 是指可缩放矢量图形(Scalable Vector Graphics,SVG)
,基于 XML 标记语言,可以用于描述二维的矢量图形。显而易见,SVG 格式提供的是矢量图,因此图片可以被无限放大而不失真或降低质量,并且可以方便地修改内容和进行定制化开发。
笔者最近在学习开发网页播放器的相关内容,了解到可以借助 SVG 实现播放和暂停按钮,以及进度条等效果。这里,介绍下如何实现一个动态的进度条效果,并进一步封装为一个 Vue 组件。
svg 标签
首先,svg 标签可以设置以下属性:
属性 | 属性值 |
---|---|
width | 宽度,比如 100 |
height | 高度,比如 100 |
viewBox | 包含 4 个参数的列表 min-x , min-y , width and height ,以空格或者逗号分隔开,比如 “0 0 100 100” 表示画布从从坐标 (0, 0) 开始截取,画布的宽、高为100 x 100。 |
version | “1.1” |
xmlns | “www.w3.org/2000/svg” |
viewBox
属性可以用于缩放图片,举个例子:
在以上3个图形中,svg 的宽高均为100,圆的半径50、宽高均为50。
- 当
viewBox="0 0 100 100"
时,圆完整展示出来,此时画布的宽高均等于圆的直径; - 当
viewBox="0 0 50 50"
时,圆展示了1/4,此时画布的宽高是50 x 50,只包含圆的1/4,需要展示在宽高100 x 100的区间上,看起来是放大的效果; - 当
viewBox="0 0 200 200"
时,圆缩小了,此时画布的宽高是200 x 200,需要展示在宽高100 x 100的区间上,看起来就是缩小的效果。
画圆弧
在上面我们实现了画圆的效果,那么我们怎么实现画圆弧的效果呢?
举个例子:
在以上3个图形中,svg 的宽高均为100,圆的半径50、宽高均为50。画圆弧的效果具体是怎么实现的呢?
首先,我们在svg标签中,设置 circle 标签的fill="transparent"
,也就是透明效果;
设置stroke: green; stroke-width: 8px; transform-origin: center;
设置圆的描边效果;接着,还需要设置stroke-dasharray
为圆的周长,stroke-dashoffset
为实际长度,也就实现了圆弧效果。
需要注意的是,stroke-dashoffset
的数值越小,圆弧越接近一个圆。
我们可以注意到,圆弧是从右侧开始画的。为了实现进度条从上方开始的效果,我们设置属性transform: rotate(-90deg);
旋转90°即可。
环形进度条效果
前面我们已经实现了画圆弧效果。这里,我们继续拓展一下,定义变量 progress 表示进度,取值范围是 [0, 1]。为了模拟进度条效果,使用定时器每秒给 progress 增加 0.05,dashOffset
动态设置为(1 - this.progress) * this.dashArray
。最终效果如下:
这里,我们可以把 radius, progress 定义在组件的 props 属性中,便于引用组件时进行传参。此外,还可以在组件中设置<slot></slot>
,便于在进度条中插入图标等,优化展示效果。比如,我们可以插入播放或暂停的图标,实现一个音乐播放器的环形进度条效果。
拓展
这里,我们用 polygon 元素实现一个播放按钮,用 rect 元素实现暂停按钮,当点击 svg 图标时,暂停播放器的倒计时,再次点击时,继续倒计时,也就实现了播放器的环形进度条效果!
<svg
:width="radius"
:height="radius"
viewBox="0 0 100 100"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
@click="togglePlay"
>
<circle
class="progress-background"
r="50"
cx="50"
cy="50"
fill="transparent"
/>
<circle
class="progress-bar"
r="50"
cx="50"
cy="50"
fill="transparent"
:stroke-dasharray="dashArray"
:stroke-dashoffset="dashOffset"
/>
<g v-if="!playing">
<polygon points="46,40 58,50 46,60" fill="palegreen" />
</g>
<g fill="palegreen" v-else>
<rect x="44" y="42" width="5" height="16" />
<rect x="52" y="42" width="5" height="16" />
</g>
</svg>
后记
本文从 SVG 标签开始,到画圆弧,再到实现一个环形进度条效果。总而言之,SVG 标签在前端开发中有着广泛的应用,可以帮助我们更优雅地定制化图片效果、实现动画等等
。