使用场景

项目上要用到一个圆环形的进度条,同时随着值的不同,颜色也不同,但是找了很多,都是水平进度条,或者径向渐变,不满足需求。

思路

canvas的api中已提供了两种,径向和线性渐变,并没有这种环形的渐变,所以很容易画出对称渐变。但是canvas提供了使用Pattern来绘制,Pattern可以是图片等其它对像,那么这里就使用到这个api,需要使用一张环形渐变的图像来绘制非对称渐变。

绘制对称环形渐变

这里使用的(水平)线性渐变。先使用createLinearGradient创建渐变,然后使用strokeStyle进行设置,然后使用stroke绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(170, 120);
var grd=ctx.createLinearGradient(0,0,170,0);
grd.addColorStop("0","black");
grd.addColorStop("0.3","magenta");
grd.addColorStop("0.5","blue");
grd.addColorStop("0.6","green");
grd.addColorStop("0.8","yellow");
grd.addColorStop(1,"red");
ctx.strokeStyle = grd;
ctx.arc(120, 120, 50, 0 ,Math.PI*2);
ctx.stroke(); // 画圆

效果如下:



绘制非对称环形渐变

先使用ps制作一张环形渐变的图片。实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var canvas = document.getElementById("canvas2");
var ctx2 = canvas.getContext('2d');
ctx2.lineWidth = 5;
var img;
img = new Image();
img.src = "./canvas.png";
if (img.complete) {
setImageFill();
} else {
img.onload = setImageFill;
}
var newFill = null;
function setImageFill() {
newFill = ctx2.createPattern(img, 'no-repeat');
ctx.beginPath();
ctx.strokeStyle = newFill;
ctx.arc(50, 50, 46, 0, Math.PI*2, false);
ctx.stroke();
}

效果如下:




效果已经基本上出现了,下面还需要让其动起来。

动态绘制

其实就是添加一个动态函数,在这里使用html5新添加的requestAnimationFrame,这个函数有兼容性的考虑,需要注意!这里不做处理!
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var canvas = document.getElementById("canvas2");
var ctx2 = canvas.getContext('2d');
ctx2.lineWidth = 5;
ctx2.lineCap="round";
var img;
img = new Image();
img.src = "canvas.png";
if (img.complete) {
setImageFill();
} else {
img.onload = setImageFill;
}
var newFill = null;
function setImageFill() {
newFill = ctx2.createPattern(img, 'no-repeat');
drawCircle(ctx2, 0,50);
}
var stop = null ;
function drawCircle(ctx, x, end) {
ctx.clearRect(0, 0, 300, 300);
ctx.beginPath();
ctx.strokeStyle = newFill;
if (x < Math.PI*2*end/100) {
x += Math.PI/100;
} else {
window.cancelAnimationFrame(stop)
}
ctx.arc(50, 50, 46, 0, x, false);
ctx.stroke();
stop = requestAnimationFrame(function () {
drawCircle(ctx, x ,end);
});
}

其中的drawCircle第三个参数就是对应的值。
效果如下:



演示地址

点击演示
Github

本文地址: http://wsdever.github.io/2016/08/13/20160813/