直接上代码
let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d')
/*
* 一共分成二十五份
* 360 / 25 为一份所占的宽度
* 梯形
* */
let total = 25 // 总共分为几块
let progress = 0.3 // 进度
let step = Math.PI * 2 / total // 梯形+ 空隙的步进
let gap = step * 0.3 // 空隙的大小
let x = canvas.width / 2 // 圆心坐标
let y = canvas.height / 2
let r = 100 // 外圈半径
let sr = 92 // 内圈半径
let end = progress * total // 结束位置 progress * 总共的份数
let count = 0
let frame = 1000 / 60 // 帧率
let duration = 1200 // 持续时间
// 角都是已知的
//要 求出 x y 和角度之间的关系
// x = r * sin 角 y = r( 1 - cos )
requestAnimationFrame(function b() {
count += end * frame / duration
// count = Math.floor(count)
ctx.clearRect(0, 0, canvas.width, canvas.height)
let gradient = ctx.createLinearGradient(0, 0, canvas.width, 0)
gradient.addColorStop(0.4, '#ffe07a')
gradient.addColorStop(1, '#a74004')
ctx.beginPath()
for (let i = 0; i < count; i++) {
ctx.moveTo(x + sr * Math.sin(step * i), y - sr + sr * (1 - Math.cos(step * i)))
ctx.lineTo(x + r * Math.sin(step * i), y - r + r * (1 - Math.cos(step * i)))
ctx.lineTo(x + r * Math.sin(step * (i + 1) - gap), y - r + r * (1 - Math.cos(step * (i + 1) - gap)))
ctx.lineTo(x + sr * Math.sin(step * (i + 1) - gap), y - sr + sr * (1 - Math.cos(step * (i + 1) - gap)))
ctx.lineTo(x + sr * Math.sin(step * i), y - sr + sr * (1 - Math.cos(step * i)))
}
ctx.fillStyle = gradient
ctx.fill()
ctx.beginPath()
for (let i = Math.floor(count); i < total; i++) {
ctx.moveTo(x + sr * Math.sin(step * i), y - sr + sr * (1 - Math.cos(step * i)))
ctx.lineTo(x + r * Math.sin(step * i), y - r + r * (1 - Math.cos(step * i)))
ctx.lineTo(x + r * Math.sin(step * (i + 1) - gap), y - r + r * (1 - Math.cos(step * (i + 1) - gap)))
ctx.lineTo(x + sr * Math.sin(step * (i + 1) - gap), y - sr + sr * (1 - Math.cos(step * (i + 1) - gap)))
ctx.lineTo(x + sr * Math.sin(step * i), y - sr + sr * (1 - Math.cos(step * i)))
}
ctx.fillStyle = '#a7a7a7'
ctx.fill()
if (count < end) {
requestAnimationFrame(b)
}
})
效果
颜色什么的自己修改,也可以用渐变色。
绘制的地方就不写注释了, 参数啥的可以自行修改。