有这么个环形进度条,应该怎么去实现呢
image.png
从结构来看,需要一根背景线,一个进度线,一个百分比进度条,ok,一步步来看怎么实现
1.画背景线
这个比较简单,直接arc一下, 然后stroke一下即可,看看代码
var c1 = document.querySelector('#c1')
var ctx = c1.getContext('2d')
ctx.translate(c1.width / 2, c1.height / 2)
ctx.arc(0, 0, 100, 0, Math.PI * 2)
ctx.lineWidth = 5
ctx.stroke()
ctx.beginPath()
translate将画笔放到canvas的中心,然后画一个圆,设置线的宽度为5,然后进行描边,之后开启一段新路径
2.画百分比进度条
其实这个也比较简单,只需要设置一下进度条的宽度,颜色,和圆弧的长度即可
ctx.arc(0,0,100,0,60*Math.PI/180)
ctx.lineWidth=10
ctx.strokeStyle = 'red'
ctx.stroke()
这段代码画了一条圆弧,长度为60度的角对应的弧长,设置弧宽为10,设置弧的颜色为红色,然后开始描边,看看效果
image.png
可以看出,一般情况下,我们需要弧的起点终点是圆的,这里用到了一个api,lineCap,它有三个取值
ctx.lineCap = "butt";
ctx.lineCap = "round";
ctx.lineCap = "square";
具体的请参阅这里,此处我们去round
3.画中间的百分比
这个也比较简单,先来看看代码
ctx.beginPath()
ctx.font = '30px Arial'
ctx.fillText(parseFloat((60 / 360) * 100).toPrecision(2) + '%', -20, 10)
效果如下
image.png
这样的基本的环形百分比就画好了,注意设置font时,要同时传font-size和font-family,不然没有效果
4.添加动画
js中使用动画可以有setTimeout,setInterval,requestAnimationFrame,demo中用到的是第三个,因为它会自动的去算1000中执行多少帧,从而能够平滑地做动画;这里要注意的一点就是,画进度时,要先使用clearRect去除上一次的进度,不然会有一坨数字叠加。这里跟canvas的关系不大,就不一句一句解释了,贴出全部代码吧,直接保存为html即可看到具体效果
<html>
<head>
<meta charset="utf-8">
<title>文档标题</title>
<!-- 开启响应式 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SEO页面关键词 -->
<meta name="keywords" content="your keywords">
<!-- SEO页面描述 -->
<meta name="description" content="your description">
<style>
* {
margin: 0;
padding: 0;
}
#c1 {
display: block;
margin: 10px auto;
border: 1px solid red;
width: 300;
height: 300;
}
</style>
</head>
<body>
<canvas width="600" height="600" id="c1"></canvas>
<script type="text/javascript">
var c1 = document.querySelector('#c1')
var ctx = c1.getContext('2d')
ctx.translate(c1.width / 2, c1.height / 2)
ctx.arc(0, 0, 100, 0, Math.PI * 2)
ctx.lineWidth = 5
ctx.stroke()
ctx.beginPath()
var currentAngle = 0
var currentProcess = 0
var currentPercentage = 0
function process(endAngle) {
var step = Math.PI / 60
if (currentAngle + step > endAngle) {
currentAngle = endAngle
} else {
currentAngle += step
}
ctx.beginPath()
ctx.arc(0, 0, 100, 0, currentAngle)
ctx.lineCap = 'round'
var lingrad = ctx.createLinearGradient(0, 0, 0, 150);
lingrad.addColorStop(0, '#f00');
lingrad.addColorStop(1, '#ff0');
ctx.lineWidth = 20
ctx.strokeStyle = lingrad
ctx.stroke()
ctx.beginPath()
currentProcess = (parseFloat(currentAngle / endAngle) * 100).F(2)
ctx.clearRect(-50, -50, 120, 100)
ctx.font = '30px Arial'
ctx.fillText((parseFloat(+currentAngle / (Math.PI * 2))*100).toPrecision(2) + '%', -30, 5)
if (currentAngle >= endAngle) {
currentProcess = 1
currentAngle = endAngle
return
}
requestAnimationFrame(() => {
process(endAngle)
}, 100)
}
process(Math.PI * 1 / 3)
</script>
</body>
</html>
网友评论