产品需求
小程序圆形进度条来表示任务的完成进度。
需求分析
初步分析:
- canvas绘制背景
- canvas绘制进度条
- canvas绘制数字(为什么不用div绝对定位,原因是div会解析成小程序的view标签,而canvas是客户端创建的原生组件,原生组件的层级是最高的,所以页面中的其他组件无论设置 z-index 为多少,都无法盖在原生组件上)
文件结构
<template>
<div class="chart">
<canvas :canvas-id="bgId" class="pie"></canvas>
<canvas :canvas-id="progressId" class="pie"></canvas>
<canvas :canvas-id="percentId" class="pie"></canvas>
</div>
</template>
<script>
export default {
props: ['radius', 'item'],
created() {
const percent = this.item.percent
// 因为是在列表中用到
this.bgId = `${this.bgId}-${this.item.id}`
this.progressId = `${this.progressId}-${this.item.id}`
this.percentId = `${this.percentId}-${this.item.id}`
// 绘制背景
this.handleDrawBg()
// 绘制进度条
this.handleDrawCircle(percent)
// 绘制百分数字
this.handleDrawPercent(percent)
},
methods: {
handleDrawBg() {},
handleDrawCircle(percent = 0) {},
handleDrawPercent(percent = 0){}
}
}
</script>
<style lang="scss">
.chart {
position: relative;
.pie {
position: absolute;
top: 0;
right: 10px;
height: 100px;
width: 100px;
}
}
</style>
复制代码
文件中canvas-id
用了变量绑定了变量,是因为列表会渲染多个相同canvas-id
的canvas
,导致除第一个canvas之外其他canvas标签自动加上了display:none
绘制背景
handleDrawBg() {
// 创建 canvas 的绘图上下文 CanvasContext 对象
var ctx = wx.createCanvasContext(this.bgId)
const radius = this.radius || 40
ctx.setLineWidth(10) // 设置圆环的宽度
ctx.setStrokeStyle('#EDF0F6') // 设置填充颜色
ctx.beginPath() // 开始创建一个路径
ctx.arc(radius + 10, radius + 10, radius - 10, 0, 2 * Math.PI, false) // 圆点(50,50)内半径为30
ctx.stroke() // // 画出当前路径
ctx.draw()
},
复制代码
效果如下:
绘制进度圆环
一个圆周的弧度是2π,一个圆周是360度,那么一度角对应2π/360弧度。 于是得出,任意度数角α对应的弧度是α*π/180
handleDrawCircle(percent = 0) {
var ctx = wx.createCanvasContext(this.progressId)
const radius = this.radius || 40
var gradient = ctx.createLinearGradient(90, 0, 0, 90) // 圆环为从右上到左下渐变
gradient.addColorStop('0', '#00B9FF')
gradient.addColorStop('1.0', '#98DEF8')
ctx.setLineWidth(10) // 宽度为10
ctx.setStrokeStyle(gradient) // 填充颜色
// 若设置线条的端点样式为圆形,当进度为0时会显示一个圆点
if (percent !== 0) {
ctx.setLineCap('round')
}
ctx.beginPath()
// -Math.PI / 2 将起始角设在12点钟位置
ctx.arc(
radius + 10,
radius + 10,
radius - 10,
-Math.PI / 1.75,
percent / 100 * Math.PI * 2 - Math.PI / 1.75,
false
)
ctx.stroke()
ctx.draw()
},
复制代码
效果图:
绘制百分比
文字有个加粗效果。因此文字绘制了两次有个叠加效果,看起来和加粗效果一样
handleDrawPercent(percent = 0) {
var ctx = wx.createCanvasContext(this.percentId)
ctx.setFontSize(20)
ctx.setFillStyle('#41444A')
ctx.fillText(percent, 34, 59 - 0.5)
ctx.fillText(percent, 34 - 0.5, 59)
ctx.setFontSize(13)
ctx.fillText('%', 57, 59)
ctx.draw()
}
复制代码
最后
文笔粗糙,请多指教。