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 }
运行效果: