$(document).ready(function () {
var graph = {};
function addEvent(obj, event, fuc) {
if (obj.addEventListener) {
obj.addEventListener(event, fuc);
} else if (obj.attachEvent) {
obj.attachEvent("on" + event, function (event) {
//使作用域指向obj(事件对象)
return fuc.call(obj, event);
});
}
}
var Stage = function () {
this.canvas = $("#mycanvas");
this.width = this.canvas.width();
this.height = this.canvas.height();
this.canvas = document.getElementById("mycanvas");
this.ctx = this.canvas.getContext("2d");
};
graph["Stage"] = Stage;
var Text1 = function (content, x, y, font, color) {
content = content || "";
x = x || 0;
y = y || 0;
font = font || "30px serif";
color = color || "RGB(0,0,0)";
this.stage = new graph.Stage();
this.content = content;
this.x = x;
this.y = y;
this.font = font;
this.color = color;
this.write(this.content);
};
Text1.prototype.write = function () {
//this.content = content;
this.stage.ctx.save();
this.stage.ctx.font = this.font;
this.stage.ctx.StrokeStyle = this.color;
this.stage.ctx.fillText(this.content, this.x, this.y);
this.stage.ctx.restore();
};
graph["Text1"] = Text1;
var Sector = function (startAngle, endAngle, color, num, rate) {
this.startAngle = startAngle;
this.endAngle = endAngle;
this.color = color;
this.num = num;
this.rate = rate;
};
graph["Sector"] = Sector;
var Circle = function (data) {
data = data || [];
this.stage = new graph.Stage;
this.ctx = this.stage.ctx;
//this.text = new graph.Text1("",400,400,'30px serif',"RGB(0,0,0)");
//圆的中点和半径
this.x = 200;
this.y = 200;
this.radius = 100;
//将传入的数据送到Circle中作为它的属性
this.data = data;
this.sum = 0;
//扇形的始终
this.start = 0;
this.end = 0;
this.sectors = [];
this.init();
};
Circle.prototype.init = function () {
for (var i = 0; i < this.data.length; i++) {
this.sum += this.data[i][1];
}
};
Circle.prototype.draw = function (data) {
for (i = 0; i < this.data.length; i++) {
//随机分配每块扇形的颜色
var red = Math.round(Math.random() * 155) + 100;
var green = Math.round(Math.random() * 155) + 100;
var blue = Math.round(Math.random() * 155) + 100;
this.ctx.fillStyle = "RGB(" + red + "," + green + "," + blue + ")";
var color = this.ctx.fillStyle;
this.ctx.beginPath();
this.ctx.moveTo(this.x, this.y);
this.end = this.start + (this.data[i][1] / this.sum) * 2 * Math.PI;
this.ctx.arc(this.x, this.y, this.radius, this.start, this.end, false);
this.ctx.fill();
this.ctx.fillRect(400, 100 + 22 * i, 20, 20);
this.ctx.beginPath();
this.ctx.fillStyle = "RGB(0,0,0)";
var text1 = new graph.Text1(this.data[i][0], 440, 120 + 22 * i, '20px serif', "RGB(0,0,0)");
var text2 = new graph.Text1((this.data[i][1] / this.sum * 100).toFixed(2) + "%",
this.x + this.radius * (Math.cos(this.start) + Math.cos(this.end)) / 2,
this.y + this.radius * (Math.sin(this.start) + Math.sin(this.end)) / 2, '10px serif', "RGB(0,0,0)");
//var text2 = new graph.Text1((this.data[i]/this.sum).toFixed(2)+"%",
// this.x+this.radius*Math.cos(this.start+this.end)/2,
// this.y+this.radius*Math.sin(this.start+this.end)/2,'30px serif',"RGB(0,0,0)");
//每次循环将扇形信息加到里面
/*this.sectors.push(new graph.Sector({
startAngle : this.start,
endAngle : this.end,
color : color,
num : this.data[i][1],
rate : (this.data[i][1]/this.sum).toFixed(2)
}));*/
this.sectors.push(new graph.Sector(this.start, this.end, color, this.data[i][1], (this.data[i][1] / this.sum).toFixed(2)));
this.start += Math.PI * 2 * (this.data[i][1] / this.sum);
}
};
Circle.prototype.addEvent = function (type, fuc) {
var that = this;
var func = function (e) {
e = event || window;
var x = e.clientX - that.x;
var y = e.clientY - that.y;
if (x * x + y * y > that.radius * that.radius) return false;
else {
fuc(e);
}
};
addEvent.call(this, this.stage.canvas, type, func);
};
//graph["Stage"] = Stage;
graph["Circle"] = Circle;
var display_mes = $("#display");
//var is_display = false;
//数据包用二维数组来表示,(这里用对象来表示数据是不是更好?)
//var data = [10,20,30,40,50];
var data = [
["kind_1", 10],
["kind_2", 20],
["kind_3", 30],
["kind_4", 40],
["kind_5", 50]
];
//建立一个Circle的对象并且画之
var circle = new graph.Circle(data);
circle.draw();
//鼠标放到某个扇区可以显示扇区信息
circle.addEvent("mousemove", function (e) {
//atan2介于-PI到PI之间...
var angle1 = Math.atan2(e.clientY - circle.y, e.clientX - circle.x);
//所以要进行适当的换算
var angle2 = angle1 + Math.PI * 2;
//这个算法明显需要改进,能不能不用这样?
for (var i = 0; i < data.length; i++) {
//也可以分两次讨论,一次是在原点以下,一次在原点以上
if (((angle1 > (circle.sectors[i].startAngle)) && (angle1 < (circle.sectors[i].endAngle))) || ((angle2 > (circle.sectors[i].startAngle)) && (angle2 < (circle.sectors[i].endAngle)))) {
//is_display = true;
display_mes.html("kind_" + (i + 1) + "的数量:" + circle.sectors[i].num +
"<br>kind_" + (i + 1) + "的比例:" + circle.sectors[i].rate);
display_mes.addClass("display");
//break;
}
}
//我想要在离开饼图的时候使信息消失,怎么处理?
//if(is_display == false){
// display_mes.hide("slow");
//}
});
});
<body>
<canvas id="mycanvas" width=500 height=400></canvas>
<div id="display"></div>
</body>
canvas {
border: 1px solid #4c4c4c;
border-radius:10px;
box-shadow:5px 5px rgba(0, 100, 100, .6);
}
.display {
position: absolute;
top: 300px;
left: 300px;
width:200px;
height:100px;
background:#ffcc66;
border-radius:10px;
box-shadow:5px 5px rgba(100, 100, 100, .6);
text-shadow:1px 1px 1px rgba(0, 0, 0, .3);
}