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 标签在前端开发中有着广泛的应用,可以帮助我们更优雅地定制化图片效果、实现动画等等

原文链接:https://juejin.cn/post/7216681666106769464 作者:觅迹

(0)
上一篇 2023年4月3日 下午4:58
下一篇 2023年4月3日 下午5:08

相关推荐

发表回复

登录后才能评论