用初中数学知识撸一个canvas环形进度条

周末好,今天给大家带来一款接地气的环形进度条组件vue-awesome-progress。近日被设计小姐姐要求实现这么一个环形进度条效果,大体由四部分组成,分别是底色圆环,进度弧,环内文字,进度圆点。设计稿截图如下:

环形进度条设计稿

我的第一反应还是找现成的组件,市面上很多组件都实现了前3点,独独没找到能画进度圆点的组件,不然稍加定制也能复用。既然没有现成的组件,只有自己用vue + canvas撸一个了。

我也很无奈啊

效果图

先放个效果图,然后再说下具体实现过程,各位看官且听我慢慢道来。

环形进度条效果图

安装与使用

源码地址,欢迎star和提issue。

安装 npm install --save vue-awesome-progress 使用 全局注册 import Vue from 'vue' import VueAwesomeProgress from "vue-awesome-progress" Vue.use(VueAwesomeProgress) 局部使用 import VueAwesomeProgress from "vue-awesome-progress" export default { components: { VueAwesomeProgress }, // 其他代码 } webpack配置

由于当前版本发布时,未进行babel编译,因此使用时需要自行将vue-awesome-progress纳入babel-loader的解析范围。示例如下:

// resolve函数是连接路径的,方法体是path.join(__dirname, "..", dir) { test: /\.js$/, loader: "babel-loader", include: [ resolve("src"), resolve("node_modules/vue-awesome-progress") ] } 静态展示

任何事都不是一蹴而就的,我们首先来实现一个静态的效果,然后再实现动画效果,甚至是复杂的控制逻辑。

确定画布大小

第一步是确定画布大小。从设计稿我们可以直观地看到,整个环形进度条的最外围是由进度圆点确定的,而进度圆点的圆心在圆环圆周上。

环形进度条模型

因此我们得出伪代码如下:

// canvasSize: canvas宽度/高度 // outerRadius: 外围半径 // pointRadius: 圆点半径 // pointRadius: 圆环半径 canvasSize = 2 * outerRadius = 2 * (pointRadius + circleRadius)

据此我们可以定义如下组件属性:

props: { circleRadius: { type: Number, default: 40 }, pointRadius: { type: Number, default: 6 } }, computed: { // 外围半径 outerRadius() { return this.circleRadius + this.pointRadius }, // canvas宽/高 canvasSize() { return 2 * this.outerRadius + 'px' } }

那么canvas大小也可以先进行绑定了

<template> <canvas ref="canvasDemo" :width="canvasSize" :height="canvasSize" /> </template> 获取绘图上下文

getContext('2d')方法返回一个用于在canvas上绘图的环境,支持一系列2d绘图API。

mounted() { // 在$nextTick初始化画布,不然dom还未渲染好 this.$nextTick(() => { this.initCanvas() }) }, methods: { initCanvas() { var canvas = this.$refs.canvasDemo; var ctx = canvas.getContext('2d'); } } 画底色圆环

完成了上述步骤后,我们就可以着手画各个元素了。我们先画圆环,这时我们还要定义两个属性,分别是圆环线宽circleWidth和圆环颜色circleColor。

circleWidth: { type: Number, default: 2 }, circleColor: { type: String, default: '#3B77E3' }

canvas提供的画圆弧的方法是ctx.arc(),需要提供圆心坐标,半径,起止弧度,是否逆时针等参数。

ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

我们知道,Web网页中的坐标系是这样的,从绝对定位的设置上其实就能看出来(top,left设置正负值会发生什么变化),而且原点(0, 0)是在盒子(比如说canvas)的左上角哦。

web坐标系

对于角度而言,0°是x轴正向,默认是顺时针方向旋转。

圆环的圆心就是canvas的中心,所以x, y 取outerRadius的值就可以了。

ctx.strokeStyle = this.circleColor; ctx.lineWidth = this.circleWidth; ctx.beginPath(); ctx.arc(this.outerRadius, this.outerRadius, this.circleRadius, 0, this.deg2Arc(360)); ctx.stroke();

注意arc传的是弧度参数,而不是我们常理解的360°这种概念,因此我们需要将我们理解的360°转为弧度。

// deg转弧度 deg2Arc(deg) { return deg / 180 * Math.PI }

画圆环

画文字

调用fillText绘制文字,利用canvas.clientWidth / 2和canvas.clientWidth / 2取得中点坐标,结合控制文字对齐的两个属性textAlign和textBaseline,我们可以将文字绘制在画布中央。文字的值由label属性接收,字体大小由fontSize属性接收,颜色则取的fontColor。

if (this.label) { ctx.font = `${this.fontSize}px Arial,"Microsoft YaHei"` ctx.fillStyle = this.fontColor; ctx.textAlign = 'center' ctx.textBaseline = 'middle' ctx.fillText(this.label, canvas.clientWidth / 2, canvas.clientWidth / 2); }

画文字

画进度弧

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyswfx.html