废话不多说 上代码
const progress = document.querySelector('#progress')
const ctx = progress.getContext('2d')
const colorArr = ['#fc8251', '#5470c6', '#91cd77', '#ef6567', '#f9c956', '#75bedc']
const stepsArr = [10, 50, 30]
let counter = 0
// 画布圆心
const canvasX = progress.width / 2
const canvasY = progress.height / 2
// 将一个圆分成一百份
const circle = Math.PI * 2 / 100
let steps = 0
// 外圆弧
ctx.strokeStyle = '#e8eaec'
ctx.lineWidth = 5
ctx.save()
ctx.beginPath()
ctx.arc(canvasX, canvasY, 10, 0, Math.PI * 2, false)
ctx.stroke()
ctx.closePath()
ctx.restore()
// 内圆弧
for (let i = 0; i < stepsArr.length; i++) {
ctx.strokeStyle = colorArr[i]
ctx.lineWidth = 5
ctx.save()
ctx.beginPath()
counter += stepsArr[i]
if (i === 0) {
// 如果是0 从-90开始画起 同样的结尾位置别忘了-90
// 0-90~10-90
ctx.arc(canvasX, canvasY, 10, -Math.PI / 2, -Math.PI / 2 + stepsArr[i] * circle, false)
} else {
// 如不是 从上一个圆弧的结尾位置画起 别忘了也需要-90 结尾是从上一个圆弧+这次的圆弧
// 10-90 ~ 60-90
ctx.arc(canvasX, canvasY, 10, -Math.PI / 2 + steps * circle, -Math.PI / 2 + counter * circle, false)
}
ctx.stroke()
ctx.closePath()
ctx.restore()
steps += stepsArr[i]
}
// 圈内文字颜色
ctx.fillStyle = '#00000'
ctx.save()
// 50-10-100 去除小数位判断 数字个十百位 绘制的起点位置不同
if (steps.toFixed(0).length === 3) {
ctx.fillText(steps, canvasX - 8, canvasY + 3)
} else if (steps.toFixed(0).length === 1) {
ctx.fillText(steps, canvasX - 2, canvasY + 3)
} else if (steps.toFixed(0).length === 2) {
ctx.fillText(steps, canvasX - 5, canvasY + 3)
}
ctx.restore()
为什么要从-90开始呢?
可自己试一试 canvas的默认起点 是在圆的90开始的 如果想像我们人类所看到的圆的起点就需要-90
各个方法的解释