直接上代码
let canvas = document.getElementById('myCanvas')
let ctx = canvas.getContext('2d')
ctx.strokeStyle = '#0000ff';
let start = 0 // 开始角度, 暂时不用, 都从顶部开始
let end = 0.6 // progress
let count = 0 // 速度计数
let sR = 15 // 小圆弧的半径
let bR = 100 // 大圆弧外圈的半径
let {width, height} = canvas.getBoundingClientRect()
let bX = width / 2 // 大圆弧的圆心坐标 x
let bY = height / 2 // 大圆弧的圆心坐标 y
let color = '#00f'
// x, y 圆心坐标 r 半径
// arc( x, y, r, startAngle, endAngle, 方向(false顺时针 true逆时针)
// 尾的 起始位置要变化 圆心 位置变化
// 圆心从 x = bX y = bY - bR + 2*sR 大圆外圈的下面为起点
// 到 x = bX y = bY + bR - 2*sR 大圆外圈的 上面为终点
// 圆心怎么变 bX , bY 为圆心 半径为bR - sR 的一个圆
// 起点位置怎么变 bX, bY 为圆心 半径为bR - 2*sR 的一个愿
// (x - bX)^2 + (y - bY)^2 = (bR - sR)^2
// 点p 在 x = bX y = bY - bR + sR 的时候
// 角度每增长0.02Pi x和y 坐标的增量
// r*sin(0.02Pi) r - r*cos(0.02Pi)
// 里面的圆统一从0.5 PI 开始画
requestAnimationFrame(function a(time) {
count = c_bezier(0, 0, 0.58, 1, time / 1000)
console.log(count * 1000)
ctx.clearRect(0, 0, width, height)
ctx.beginPath()
ctx.fillStyle = color
// 外圈 只有结束角度需要改变
ctx.arc(bX, bY, bR, Math.PI * 1.5, Math.PI * 1.5 + Math.PI * 2 * count, false);
// 尾 圆心, 起始角 结束角 都需要改变 尾部的圆是半圆, 不能闭合
ctx.arc(bX + (bR - sR) * Math.sin(Math.PI * 2 * count), bY - bR + sR + (bR - sR) * (1 - Math.cos(Math.PI * 2 * count)), sR, (Math.PI * 1.5 + Math.PI * 2 * count) % (Math.PI * 2), (Math.PI * 1.5 + Math.PI + Math.PI * 2 * count)% (Math.PI * 2), false)// 绘制路径
// 内圈
ctx.arc(bX, bY, bR - 2 * sR, (Math.PI * 0.5 + Math.PI + Math.PI * 2 * count)% (Math.PI * 2), Math.PI * 1.5, true)
// 头 如果开始角度不变, 就不需要变, 位置固定。
// path.moveTo(bX, bY - bR + 2 * sR)
ctx.arc(bX, bY - bR + sR, sR, Math.PI * 0.5, Math.PI * 0.5 - Math.PI, false)
ctx.closePath()
ctx.fill()
// 在尾部画一个空心圆 r = sR / 4
// 起始点 是起始点 圆心是圆心
ctx.beginPath()
ctx.fillStyle = '#fff'
ctx.arc(bX + (bR - sR) * Math.sin(Math.PI * 2 * count), bY - bR + sR + (bR - sR) * (1 - Math.cos(Math.PI * 2 * count)), sR / 4, Math.PI * 0.5 + Math.PI * 2 * count, Math.PI * 0.5 + 2 * Math.PI + Math.PI * 2 * count, false)
ctx.closePath()
ctx.fill()
if (count < end) {
requestAnimationFrame(a)
}
})
// 缓动函数
function c_bezier(p0,p1,p2,p3,t){
return p0*(1-t)*(1-t)*(1-t)+3*p1*t*(1-t)*(1-t)+3*p2*t*t*(1-t)+p3*t*t*t;
}
复制可直接使用。
最近需要用一个圆形的进度条,在头部还要有个小圈圈, 但是网上的版本好像都是画一条线,设置线宽, 并不能满足要求, 所以只好自己写一个。
count是每一次绘制的时候的进度, 不过这个缓动函数虽然是先快后慢, 但是还是看不大出来效果。
颜色可以设置渐变, 可以设置阴影,直接给ctx设置shadow就行。
效果