简介

这两天公司在做手机管家,很意外也是第一次听说公司的手机管家是用JS写的,然后各种费解(又一次无知了)。正巧对canvas有一些见解,所以永哥叫我画一个随杀毒变化的圆形进度条,然后就不废话,直接上图吧。

进度条!

jsfiddle上效果

先在jsfiddle中看看效果



代码分析

① 如何取得进度条上的值

在杀毒的正式版本中,后台会给我发实时变化的数据,因为我在调试,所以自己加了进度条控件 <input type="range" value="60" id="range" />,在Chrome浏览器上是一个可以左右拉并且有范围的控件。

获得控件上的值只要用DOM的getElementById方法

1
2
3
4
5
6
var range = document.getElementById('range');
var num1 = parseInt(range.value);
range.onchange = function(){
  num1 = parseInt(range.value);   
  move(point);
};

我这里因为是测试版本,所以用了num1命名,不建议你写代码用这些没有意义的命名,num1实际上就是查毒时你得的分数,这里千万要注意的是用range.value获得类型是字符串的,但咱们需要的是一个int类型的,所以你可以用new Number(range.value)或者parseInt(range.value)两种方法将字符串转化为整数类型。你先别考虑move(point)这个函数调用。这里特别要强调的是range.onchange,这其实是控件改变时触发事件,这个事件也很管用,很多网站注册账号时,当你输入一个新的账号,他就能立刻将数据返回到后台,查询数据库,进行验证。


② 初始化

其实第一步咱们需要进行一些初始化

1
2
3
4
5
6
7
8
var    canvas = document.getElementById('mycanvas');
var   ctx = canvas.getContext('2d');
var x = 100,
  y = 100,
  r = 40,
  ringWidth = 10;       
var num = num1;
var point = 50;

(x,y,r,ringwidth)依次对应(旋转条相对于canvas的圆心坐标,圆心半径,圆环宽度),因为在函数中咱可能会重复用到,所以咱们命名了变量。point是一个实时变化的分数,动画效果是逐渐+1或者-1来实现的,用一个point咱可以随意地操作进度条。num咱们在函数中介绍。


③ 动画函数

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
var move = function(point){
      num = num1;
      /*每次画图先将图像擦除*/
      ctx.clearRect(x-r-5,y-r-5,2*(r+5),2*(r+5));
      
      /*画圆环*/
      ctx.beginPath();
      ctx.fillStyle = "transparent";
      ctx.arc(x,y,r+ringWidth/2,0,2*Math.PI);
      ctx.fill();
      ctx.beginPath();
      ctx.fillStyle = "transparent";
      ctx.arc(x,y,r-ringWidth/2,0,2*Math.PI);    
      ctx.fill();   
      ctx.beginPath();
      ctx.lineWidth = ringWidth;
      var angle = 1.5*Math.PI-point*Math.PI/50;
      
      /*canvas中只有线性渐变和放射型渐变,我还没想出好的方法,所以讲圆分成了左右两个半圆来处理*/
      var leftGrad,rightGrad;

      /*每个分值都会有不同的渐变*/
      if(point <= 50){
          leftGrad =   ctx.createLinearGradient(x,y-r,x,y+r);
          leftGrad.addColorStop(0.1,'#ff5151');   // 红
          leftGrad.addColorStop(0.5,'#ECD806');   // 黄
          leftGrad.addColorStop(1,'#dfd706');     // 黄
          ctx.strokeStyle = leftGrad;
          ctx.arc(x,y,r,1.5*Math.PI,angle,true);
      }
      else if(point <= 70){
          leftGrad =   ctx.createLinearGradient(x,y-r,x,y+r);          
          leftGrad.addColorStop(0.1,'#ff5151');   // 红
          leftGrad.addColorStop(0.5,'#ECD806');   // 黄 
          leftGrad.addColorStop(0.8,'#dfd706');   // 黄 
          leftGrad.addColorStop(1,'#7FCF00');     //绿
          ctx.beginPath();
          ctx.strokeStyle = leftGrad;        
          ctx.arc(x,y,r,1.5*Math.PI,0.5*Math.PI,true);
          ctx.stroke();
          ctx.beginPath();
          rightGrad = ctx.createLinearGradient(x,y+r+ringWidth/2.5,x,y);
          rightGrad.addColorStop(0.2,'#7FCF00');  //绿
          ctx.strokeStyle = rightGrad;
          ctx.arc(x,y,r,0.5*Math.PI,angle,true);
      }
      else if(point < 100){
          leftGrad =   ctx.createLinearGradient(x,y-r,x,y+r);          
          leftGrad.addColorStop(0.1,'#ff5151');   // 红
          leftGrad.addColorStop(0.5,'#ECD806');   // 黄 
          leftGrad.addColorStop(0.8,'#dfd706');   // 黄
          leftGrad.addColorStop(1,'#7FCF00');
          ctx.beginPath();
          ctx.strokeStyle = leftGrad;        
          ctx.arc(x,y,r,1.5*Math.PI,0.5*Math.PI,true);
          ctx.stroke();
          ctx.beginPath();
          rightGrad = ctx.createLinearGradient(x,y+r,x,y);
          rightGrad.addColorStop(1,'#7FCF00');  //绿
          ctx.strokeStyle = rightGrad;
          ctx.arc(x,y,r,0.5*Math.PI,angle,true);        
      }
      else if(point === 100){
          ctx.strokeStyle = "#7FCF00";
          ctx.arc(x,y,r,0,2*Math.PI,true);          
      }    
      ctx.stroke();
      /*当动画的分数小于杀毒分数时,动画分数增加*/
      if(num > point){
          point++;      
      }
      /*当动画的分数大于杀毒分数时,动画分数减小*/
      if(num < point){
          point--;
      }
      /*实现动画*/
      setTimeout(function(){
          move(point);
      },30);    
};

再次说明尽量不要这样写函数,我本来是想拿出一个对象来讲的,我这样写的规范完全是蒙蔽了初学者,所以尽量不要照搬代码,我这里只是说思想罢了。

在移动控件的时候,动画会有抖动,我分析应该是因为控件的变化是实时的,像mousemove那样,超过了动画的帧,造成了抖动。在查毒测试中,是没有这样抖动的。