canvas绘制饼状图动画
1、HTML
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
6 <title>饼状图面向对象版本</title>
7 <style>
8 body {
9 padding: 0;
10 margin: 0;
11 background-color: #f0f0f0;
12 overflow: hidden;
13 }
14 </style>
15 <script src="bower_components/konva/konva.min.js"></script>
16 <script src="js/PieChart.js"></script>
17 </head>
18 <body>
19 <div id="container">
20 </div>
21
22 <script>
23 //创建舞台
24 var stage = new Konva.Stage({
25 container: 'container',
26 width: window.innerWidth,//全屏
27 height: window.innerHeight
28 });
29
30 //创建层
31 var layer = new Konva.Layer();
32 stage.add(layer);
33
34 //中心点坐标
35 var cenX = stage.width() / 2;
36 var cenY = stage.height() / 2;
37
38 var data = [
39 { name: "前端", value: .25, color: '#e0e' },
40 { name: "php", value: .2, color: 'orange'},
41 { name: "UI", value: .3, color: 'blue' },
42 { name: "C++", value: .05, color: 'green' },
43 { name: "游戏", value: .1, color: 'purple'},
44 { name: "Java", value: .1, color: 'red' }
45 ];
46
47 var p = new PieChart({
48 x: cenX,
49 y: cenY,
50 r: 100,
51 data: data
52 });
53
54 p.addToGroupOrLayer( layer );
55 layer.draw();
56
57 p.playAnimate();
58
59 </script>
60 </body>
61 </html>
2、PieChart.js
1 //英 [paɪ] 美 [paɪ]
2 function PieChart( option ) {
3 this._init( option );
4 }
5
6 PieChart.prototype = {
7 _init: function( option ) {
8 this.x = option.x || 0;
9 this.y = option.y || 0;
10 this.r = option.r || 0;
11 this.data = option.data || [];
12
13 //饼状图所有的 物件的组
14 this.group = new Konva.Group({
15 x: this.x,
16 y: this.y
17 });
18
19 //饼状图:所有的 扇形的组
20 this.wedgeGroup = new Konva.Group({
21 x: 0,
22 y: 0
23 });
24
25 //饼状图: 所有的文字的组
26 this.textGroup = new Konva.Group({
27 x: 0,
28 y: 0
29 });
30
31 this.group.add( this.wedgeGroup );
32 this.group.add( this.textGroup );
33
34 var self = this;
35 var tempAngel = -90;//从-90开始绘制
36
37 this.data.forEach(function(item, index ) {
38 //把每条数据创建成一个扇形
39 var angle = 360 * item.value;//当前扇形的角度
40 //创建一个扇形
41 var wedge = new Konva.Wedge({
42 x: 0, //扇形圆心坐标
43 y: 0,
44 angle: angle , //扇形的角度
45 radius: self.r, //扇形的半径
46 fill: item.color, //扇形的填充颜色
47 rotation: tempAngel //扇形的旋转角度
48 });
49
50 self.wedgeGroup.add( wedge );
51
52 //绘制文本的 角度
53 var textAngle = tempAngel + 1/2 * angle;
54
55 //绘制的 百分比的文本
56 var text = new Konva.Text({
57 x: (self.r+20) * Math.cos(Math.PI/ 180 * textAngle ),
58 y: (self.r+20) * Math.sin(Math.PI/ 180 * textAngle ),
59 text: item.value*100 +'%',
60 fill: item.color
61 });
62
63 //根据角度判断设置文字的 位置
64 if( textAngle > 90 && textAngle < 270 ) {
65 //让文本向左边 移动文字宽度的位置。
66 text.x( text.x() - text.getWidth() );
67 }
68
69 self.textGroup.add( text );
70
71 tempAngel += angle;
72 });
73 //绘制所有的楔形
74
75 //绘制文字
76
77 //绘制圆环的线
78 var cir = new Konva.Circle({
79 x: 0,
80 y: 0,
81 radius: this.r+10,
82 stroke: '#ccc',
83 strokeWidth: 2
84 });
85
86 this.group.add( cir );
87
88 this._animateIndex = 0;
89 },
90 playAnimate: function() {
91
92 var self = this;
93 //根据索引显示动画
94 //把所有扇区 角度设置为0
95 if( this._animateIndex == 0 ) {
96 //拿到所有的 扇形
97 this.wedgeGroup.getChildren().each(function(item, index ){
98 item.angle(0);
99 });
100 }
101
102 //展示当前索引对应的动画
103 var item = this.wedgeGroup.getChildren()[this._animateIndex];
104 item.to({
105 angle: this.data[this._animateIndex].value * 360,
106 duration: 2 * this.data[this._animateIndex].value,
107 onFinish: function() {
108 self._animateIndex ++;
109 if( self._animateIndex >= self.data.length) {
110
111 self._animateIndex = 0;//让他的索引再回到0
112
113 //************************重点***********************
114 return;// 会把整个递归执行完成。
115 }
116 //继续执行当前方法,播放下一个动画
117 self.playAnimate();
118 }
119 });
120 },
121 //把饼状图添加到层里面的方法
122 addToGroupOrLayer: function( arg ) {
123 arg.add( this.group );
124 }
125 }
运行效果: