canvas绘制饼状图动画
1、HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>饼状图面向对象版本</title>
<style>
body {
padding: 0;
margin: 0;
background-color: #f0f0f0;
overflow: hidden;
}
</style>
<script src="bower_components/konva/konva.min.js"></script>
<script src="js/PieChart.js"></script>
</head>
<body>
<div id="container">
</div> <script>
//创建舞台
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,//全屏
height: window.innerHeight
}); //创建层
var layer = new Konva.Layer();
stage.add(layer); //中心点坐标
var cenX = stage.width() / 2;
var cenY = stage.height() / 2; var data = [
{ name: "前端", value: .25, color: '#e0e' },
{ name: "php", value: .2, color: 'orange'},
{ name: "UI", value: .3, color: 'blue' },
{ name: "C++", value: .05, color: 'green' },
{ name: "游戏", value: .1, color: 'purple'},
{ name: "Java", value: .1, color: 'red' }
]; var p = new PieChart({
x: cenX,
y: cenY,
r: 100,
data: data
}); p.addToGroupOrLayer( layer );
layer.draw(); p.playAnimate(); </script>
</body>
</html>
2、PieChart.js
//英 [paɪ] 美 [paɪ]
function PieChart( option ) {
this._init( option );
} PieChart.prototype = {
_init: function( option ) {
this.x = option.x || 0;
this.y = option.y || 0;
this.r = option.r || 0;
this.data = option.data || []; //饼状图所有的 物件的组
this.group = new Konva.Group({
x: this.x,
y: this.y
}); //饼状图:所有的 扇形的组
this.wedgeGroup = new Konva.Group({
x: 0,
y: 0
}); //饼状图: 所有的文字的组
this.textGroup = new Konva.Group({
x: 0,
y: 0
}); this.group.add( this.wedgeGroup );
this.group.add( this.textGroup ); var self = this;
var tempAngel = -90;//从-90开始绘制 this.data.forEach(function(item, index ) {
//把每条数据创建成一个扇形
var angle = 360 * item.value;//当前扇形的角度
//创建一个扇形
var wedge = new Konva.Wedge({
x: 0, //扇形圆心坐标
y: 0,
angle: angle , //扇形的角度
radius: self.r, //扇形的半径
fill: item.color, //扇形的填充颜色
rotation: tempAngel //扇形的旋转角度
}); self.wedgeGroup.add( wedge ); //绘制文本的 角度
var textAngle = tempAngel + 1/2 * angle; //绘制的 百分比的文本
var text = new Konva.Text({
x: (self.r+20) * Math.cos(Math.PI/ 180 * textAngle ),
y: (self.r+20) * Math.sin(Math.PI/ 180 * textAngle ),
text: item.value*100 +'%',
fill: item.color
}); //根据角度判断设置文字的 位置
if( textAngle > 90 && textAngle < 270 ) {
//让文本向左边 移动文字宽度的位置。
text.x( text.x() - text.getWidth() );
} self.textGroup.add( text ); tempAngel += angle;
});
//绘制所有的楔形 //绘制文字 //绘制圆环的线
var cir = new Konva.Circle({
x: 0,
y: 0,
radius: this.r+10,
stroke: '#ccc',
strokeWidth: 2
}); this.group.add( cir ); this._animateIndex = 0;
},
playAnimate: function() { var self = this;
//根据索引显示动画
//把所有扇区 角度设置为0
if( this._animateIndex == 0 ) {
//拿到所有的 扇形
this.wedgeGroup.getChildren().each(function(item, index ){
item.angle(0);
});
} //展示当前索引对应的动画
var item = this.wedgeGroup.getChildren()[this._animateIndex];
item.to({
angle: this.data[this._animateIndex].value * 360,
duration: 2 * this.data[this._animateIndex].value,
onFinish: function() {
self._animateIndex ++;
if( self._animateIndex >= self.data.length) { self._animateIndex = 0;//让他的索引再回到0 //************************重点***********************
return;// 会把整个递归执行完成。
}
//继续执行当前方法,播放下一个动画
self.playAnimate();
}
});
},
//把饼状图添加到层里面的方法
addToGroupOrLayer: function( arg ) {
arg.add( this.group );
}
}
运行效果: