实现效果:
实现逻辑:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML5 Canvas 圆形进度条并显示数字百分比</title>
</head>
<body>
<canvas id="canvas" width="250" height="250" style="background:#fff;"></canvas>
<script>
// 环形进度条基类
class CircleProgress {
// 初始化参数
constructor(params){
this.canvasId = params.canvasId; // canvas id
this.secord = params.secord || 0; // 分数
this.speed = params.speed || 0.1; // 控制加载的快慢
this.circleRadius = params.circleRadius || 100; // 圆形半径
// 底圆
this.circleColor= params.circleColor || 'rgba(40, 201, 137, 0.2)' // 底圆颜色
this.circleLineWidth = params.circleLineWidth || 0 // 底圆边框
this.circleLineColor= params.circleLineColor || 'blue' // 底圆边框颜色
// 进度圆环
this.progressLineWidth = params.progressLineWidth || 6; // 进度条圆宽
this.progressColor= params.progressColor || '#28c989' // 进度条边框
// 文字
this.fontColor = params.fontColor || '#28c989' // 文字颜色
this.fontSize = params.fontSize || 40 // 字号
this.fontFamily = params.fontFamily || 'Arial' // 字体
this.completeCallback = params.completeCallback || null // 绘制完成的回调地址
this.run()
}
// 执行动画
run(){
this.init();
let _this = this;
(function drawFrame() {
if(_this.curSecord >= _this.secord){
_this.drawSpirit(_this.secord);
_this.completeCallback && _this.completeCallback()
return;
}
window.requestAnimationFrame(drawFrame);
_this.drawSpirit(_this.curSecord);
_this.curSecord += _this.speed
}());
}
// 执行动作
drawSpirit(secord){
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.drawCircle();
this.drawProgress(secord);
this.drawText(secord);
}
// 设置画图基础属性
init(){
this.canvas = document.getElementById(this.canvasId); //获取canvas元素
this.context = this.canvas.getContext('2d'); // 获取画图环境,指明为2d
this.centerX = this.canvas.width / 2; //Canvas中心点x轴坐标
this.centerY = this.canvas.height / 2; //Canvas中心点x轴坐标
this.rad = Math.PI * 2 / 100; //将360度分成100份,那么每一份就是rad度
this.curSecord = 0; // 当前展示的分数
}
//绘制底圆
drawCircle() {
this.context.save();
this.context.beginPath();
this.context.arc(this.centerX, this.centerY, this.circleRadius, 0, Math.PI * 2, false);
if(this.circleLineWidth){
this.context.lineWidth = this.circleLineWidth; //设置线宽
this.context.strokeStyle = this.circleLineColor;
this.context.stroke(); //执行绘制
}
this.context.fillStyle = this.circleColor;//绘制样式,图形颜色
this.context.fill();//调用样式
this.context.closePath();
this.context.restore();
}
//绘制进度圆环
drawProgress(n) {
this.context.save();
this.context.beginPath(); //路径开始
let circleRadius = this.circleRadius - parseInt(this.progressLineWidth / 2) + 1
if(this.circleLineWidth){
circleRadius = this.circleRadius + parseInt(this.progressLineWidth / 2) - 3
}
this.context.arc(this.centerX, this.centerY, circleRadius, -Math.PI / 2, -Math.PI / 2 + n * this.rad, false); //用于绘制圆弧context.arc(x坐标,y坐标,半径,起始角度,终止角度,顺时针/逆时针)
this.context.strokeStyle = this.progressColor; //设置描边样式
this.context.lineWidth = this.progressLineWidth; //设置线宽
this.context.stroke(); //绘制
this.context.closePath(); //路径结束
this.context.restore();
}
//百分比文字绘制
drawText(n) {
this.context.save(); //save和restore可以保证样式属性只运用于该段canvas元素
this.context.fillStyle = this.fontColor; //设置描边样式
this.context.font = this.fontSize + 'px ' + this.fontFamily; //设置字体大小和字体
//绘制字体,并且指定位置
this.context.fillText(n.toFixed(0), this.centerX - this.fontSize / 2, this.centerY + this.fontSize / 3);
this.context.restore();
}
}
new CircleProgress({
canvasId: 'canvas',
secord: 80,
speed: 2,
progressColor: 'red',
completeCallback(){
console.log('执行完毕')
}
})
</script>
</body>
</html>