> 文档中心 > SVG绘制圆环进度条

SVG绘制圆环进度条

在我们的大屏可视化项目中,经常会用到各种各样的图表。与传统的表格展示、枯燥的文字阐述相比,图表展示则使用户看起来更加直观、数据的展示则更加一目了然。本文基于svg绘图技术结合前端技术栈vue,以工作中常用的环形进度条为例,简单阐述一下绘制进度条的一些思路,希望能和大家共勉

思路讲解:绘制圆环,选型技术有多样,比如可以使用canvas绘制、使用div模拟,使用echarts插件等等,这里以svg技术为例。说起绘制圆环,我们可以使用svg中的circle标签,当然也可以使用path标签,一个圆环作为背景,另一个圆环作为进度环。这里就有一个疑问,既然都是圆,怎么根据实际的数值绘制对应的弧度呢?这里就需要用到一个高级的css属性,stroke-dashoffset-具体用法可以查看相关api文档。在大多数的业务场景中,环形进度条总是奇形怪状,例如有的环形进度条像是带有刻度的,一段一段的,这就需要用到另一个高级css属性了,stroke-dasharray。使用stroke-dashoffset和stroke-dasharray,结合svg中的渐变和旋转等知识点,我们可以绘制出各种各样的进度条,如下图:

基于以上思路,首先我们来封装一个进度条组件,代码如下

  
export default { name: "Progress", props: { rate: { type: Number, default: 0, }, bgRingColor: { type: String, default: "#25b489", }, ringColor: { type: String, default: "#67C23A", }, strokeLinecap: { type: String, default: "round", }, strokeWidth: { type: Number, default: 20, }, part: { type: Number, default: 20, }, partGap: { type: Number, default: 12, }, showGradient: { type: Boolean, default: false, }, gradient: { type: Object, default: () => { return { id: "svg-linear-gradient", x1: "0%", y1: "0%", x2: "0%", y2: "100%", colorStops: [ {offset: "0%",color: "yellow", }, {offset: "100%",color: "orange", }, ], }; }, }, }, computed: { radius() { return 200 - this.strokeWidth / 2; }, strokeDasharray() { return 2 * Math.PI * this.radius; }, strokeDashoffset() { let val = 0; let rate = this.rate; if (rate > 1) { rate = 1; } else if (rate < 0) { rate = 0; } if (this.strokeLinecap === "round") { val = 2 * Math.PI * this.radius * (1 - rate) + this.strokeWidth; } else { val = 2 * Math.PI * this.radius * (1 - rate); } return val; }, strokeDasharray1() { var partLength = (2 * Math.PI * this.radius) / this.part; return `${this.partGap} ${partLength - this.partGap}`; }, },};.progress { position: relative; width: 100%; height: 100%;}.progress-desc { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-family: "Microsoft YaHei"; font-size: 20px; text-align: center;}.progress-bar { transition: stroke-dashoffset 1s ease;}

到这里,我们封装了进度条的基本属性及一些必传的参数,我们就可以在在相应的组件中使用这个进度条组件了,通过配置不同的样式,就可以完成各种各样的小案例了

  
条纹进度条一
条纹进度条二
{{ `${(0.8825 * 100).toFixed(2)}%` }}
条纹进度条三
渐变进度条
{{ `${(0.8888 * 100).toFixed(2)}%` }}
条纹进度条四
{{ `${(0.5035 * 100).toFixed(2)}%` }}
完成率
条纹进度条五
普通进度条
{{ `${(0.7667 * 100).toFixed(2)}%` }}
条纹进度条六
带弧度进度条
{{ `${(0.7685 * 100).toFixed(2)}%` }}
条纹进度条七
渐变进度条
{{ `${(0.3333 * 100).toFixed(2)}%` }}
条纹进度条八
import SvgLine from "./svgline.vue";export default { name: "SVGLineIndex", components: { SvgLine, }, data() { return { myGradient: { // 同一个页面中id务必唯一 id: "svg-linear-gradient001", x1: "100%", y1: "100%", x2: "0%", y2: "0%", colorStops: [ { offset: "0%", color: "#0ae787", }, { offset: "100%", color: "#fe653c", }, ], }, }; },};.progress { display: flex; flex-wrap: wrap; justify-content: space-around; align-content: space-around; width: 100%; height: 100%; background-color: #071727; overflow: hidden;}.svg-module { width: 23%; height: 46%;}.module-content { width: 100%; height: calc(100% - 30px); padding: 10px; border: 1px solid #064774; color: #fff; box-sizing: border-box;}.module-title { position: relative; z-index: 1; width: 100%; height: 30px; line-height: 30px; font-size: 16px; text-align: center; color: #fff;}.module-title::before,.module-title::after { content: ""; position: absolute; z-index: -1; top: 0; width: 50%; height: 100%; background-image: linear-gradient(to bottom, #061223, #042c4c);}.module-title::before { left: 0; transform: skew(-45deg); transform-origin: left bottom;}.module-title::after { right: 0; transform: skew(45deg); transform-origin: right bottom;}