预期效果
html
<canvas id="circle-count" type="2d"></canvas>
style样式
#circle-count
width 120rpx
height 120rpx
逻辑代码
初始化方法:
initProgress() {
const query = uni.createSelectorQuery()
query.select("#circle-count").fields({ node: true, size: true }).exec((res) => {
canvas = res[0].node
ctx = res[0].node.getContext("2d")
// 获取retina屏幕的设备像素比
const dpr = uni.getSystemInfoSync().pixelRatio
// 根据设备像素比,扩大canvas画布的像素,使1个canvas像素和1个物理像素相等
canvas.width = toRpx(120) * dpr
canvas.height = toRpx(120) * dpr
// 将绘制比例放大
ctx.scale(dpr, dpr)
ctx.beginPath() // 开始一个新的路径
ctx.fillStyle = "#FF6951" // 设置填充的颜色
ctx.lineWidth = toRpx(8) // 设置圆环的宽度
ctx.strokeStyle = "#fff" // 设置填充的颜色
ctx.arc(toRpx(60), toRpx(60), toRpx(56), startAngle, endAngle)
ctx.fill() // 对当前路径进行填充
ctx.stroke() // 对当前路径进行描边
// 绘制中间矩形
drawRoundRect(
ctx,
toRpx(36),
toRpx(36),
"#ffffff",
toRpx(48),
toRpx(48),
toRpx(8)
)
})
}
要注意的是,这里的大小数值不能写死,因为canvas样式是rpx响应式单位,这里也根据rpx计算方法动态计算,toRpx方法如下:
// 转化rpx单位
export function toRpx(val) {
const res = uni.getSystemInfoSync()
const scaleRate = res.windowWidth / 375
return val * scaleRate
}
/**
* @description: 绘制圆角矩形
* @param {ctx} ctx
* @param {number} x 坐标
* @param {number} y 坐标
* @return {bg} 背景色
* @return {h} 矩形高度
* @return {w} 矩形宽度
* @return {radius} 圆角大小
*/
export function drawRoundRect(ctx, x, y, bg, h, w, radius) {
ctx.beginPath()
ctx.fillStyle = bg
//左上角
ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2)
ctx.lineTo(x + w - radius, y)
//右上角
ctx.arc(x + w - radius, y + radius, radius, Math.PI * 3 / 2, 0)
ctx.lineTo(x + w, y + h - radius)
//右下角
ctx.arc(x + w - radius, y + h - radius, radius, 0, Math.PI / 2)
ctx.lineTo(x + radius, y + h)
//左下角
ctx.arc(x + radius, y + h - radius, radius, Math.PI / 2, Math.PI)
ctx.lineTo(x, y + radius)
ctx.fill()
}
// 绘制圆环
render() {
const end = startAngle + (endAngle / 60) * (60 - this.time)
ctx.beginPath() // 开始一个新的路径
ctx.lineWidth = toRpx(8) // 设置圆环的宽度
ctx.strokeStyle = "#FFD957" // 设置圆环的颜色
ctx.lineCap = "round" // 设置圆环端点的形状
ctx.arc(toRpx(60), toRpx(60), toRpx(56), startAngle, end, false) // 这里最后false代表顺时针方向,如果需要逆时针方向设为true即可
ctx.stroke() // 对当前路径进行描边
}
// 倒计时定时器,
handleCountTime() {
timer = setInterval(() => {
this.time -= 0.1
this.render()
if (time < 0) {
// 计时时间到
clearInterval(timer)
}
}, 100)
}
最后,可以关注本人公众号及时获取博客内容更新