效果图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
justify-content: space-around;
align-items: center;
height: 100vh;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100px;
height: 100px;
border: 1px dashed skyblue;
}
canvas {
width: 100%;
height: 100%;
}
</style>
<script src="./draw.js"></script>
</head>
<body>
<div class="container">
<canvas id="canvas" width="200" height="200"></canvas>
</div>
<script>
const canvas = document.getElementById('canvas')
drawRing({
drawingEle: canvas,
percent: 70,
bgColor: "#eef7e4",
forecolor: "#85d824",
lineWidth: 16,
fontSize: 40,
fontFamily: '微软雅黑'
})
</script>
</body>
</html>
以下为draw.js
const drawRing = function({
drawingEle = null,
percent = 100,
bgColor = "#eef7e4",
forecolor = "#85d824",
lineWidth = 16,
fontSize = 40,
fontFamily = '微软雅黑',
}) {
/*
@drawingEle: 绘制对象
@percent:绘制圆环百分比, 范围[0, 100]
@bgcolor: 绘制圆环的背景色,颜色代码
@forecolor: 绘制圆环的前景色,颜色代码
@lineWidth: 绘制圆环的环形宽度
@fontSize: 绘制圆环中的文本的字体大小
@fontFamily: 绘制圆环中的文本的字体样式
*/
if (!drawingEle) throw new Error('绘制对象不能为空')
const context = drawingEle.getContext('2d')
// 获取圆的圆心和半径
const center_x = drawingEle.width / 2
const center_y = drawingEle.height / 2
const radius = center_x - lineWidth
// 每绘制一帧就走一步
let step = 0
// 每一步的步伐长度(弧度)
let radian = Math.PI * 2 / 100
// 绘制背景圆环
function backgroundCircle() {
//save和restore可以保证样式属性只运用于该段canvas元素
context.save()
context.beginPath()
context.lineWidth = lineWidth
context.strokeStyle = bgColor
context.arc(center_x, center_y, radius, 0, 2*Math.PI, false)
context.stroke()
context.closePath()
context.restore()
}
// 绘制运动圆环
function foregroundCircle(step) {
context.save()
context.beginPath()
context.lineWidth = lineWidth
context.strokeStyle = forecolor
context.arc(center_x, center_y, radius, -Math.PI/2, -Math.PI/2 + step * radian, false)
context.stroke()
context.closePath()
context.restore()
}
// 绘制文字
function text(step) {
context.save()
context.fillStyle = forecolor
context.font = `${fontSize}px ${fontFamily}`
const str = step.toFixed(0) + '%'
const textWidth = context.measureText(str).width
const textX = center_x - textWidth/2
const textY = center_y + fontSize/2
context.fillText(str, textX, textY)
context.restore()
}
// 执行动画
(function drawFrame() {
window.requestAnimationFrame(drawFrame) // 类似于定时器,执行频率为每秒60帧,所以一帧16秒
context.clearRect(0, 0, drawingEle.width, drawingEle.height)
backgroundCircle()
foregroundCircle(step)
text(step)
if (step >= percent) return
step += 1
}())
}