mirror of
https://github.com/TBEDP/datavjs.git
synced 2026-02-01 16:06:25 +00:00
Merge branch 'butterfly' of git://github.com/TBEDP/datavjs into butterfly
This commit is contained in:
commit
76313dd777
@ -15,11 +15,21 @@
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param {Object} node 表示在html的哪个容器中绘制该组件
|
||||
* @param {Object} options 为用户自定义的组件的属性,比如画布大小
|
||||
* Options:
|
||||
* - `width` 图宽度
|
||||
* - `height` 图高度
|
||||
*
|
||||
* - `width` 图片宽度,默认为800,表示图片高800px
|
||||
* - `height` 图片高度,默认为800
|
||||
* - `legend` 图例是否显示,默认为 true, 显示;设为false则不显示
|
||||
* - `ms` 动画持续时间,默认300
|
||||
* - `easing` 动画类型,默认“bounce”。详见rapheal相关文档,可以使用“linear”,“easeIn”,“easeOut”,“easeInOut”,“backIn”,“backOut”,“elastic”,“bounce”
|
||||
*
|
||||
* Examples:
|
||||
* create Radar Chart in a dom node with id "chart", width is 500; height is 600px;
|
||||
* ```
|
||||
* var radar = new Radar("chart", {"width": 500, "height": 600});
|
||||
* ```
|
||||
* @param {Object} container 表示在html的哪个容器中绘制该组件
|
||||
* @param {Object} options 为用户自定义的组件的属性,比如画布大小
|
||||
*/
|
||||
var Pie = DataV.extend(DataV.Chart, {
|
||||
type: "Pie",
|
||||
@ -53,6 +63,8 @@
|
||||
this.defaults.legend = true;
|
||||
this.defaults.width = 800;
|
||||
this.defaults.height = 800;
|
||||
this.defaults.ms = 300;
|
||||
this.defaults.easing = "bounce";
|
||||
|
||||
//设置用户指定的属性
|
||||
this.setOptions(options);
|
||||
@ -98,16 +110,16 @@
|
||||
* 绘制饼图
|
||||
*/
|
||||
Pie.prototype.render = function () {
|
||||
this.layout();
|
||||
var conf = this.defaults;
|
||||
var floatTag = this.floatTag;
|
||||
var that = this;
|
||||
this.layout();
|
||||
var groups = this.groups;
|
||||
|
||||
//由内外半径、起始角度计算路径字符串
|
||||
var pathCalc = d3.svg.arc()
|
||||
.innerRadius(conf.radius)
|
||||
.outerRadius(0)
|
||||
.outerRadius(conf.radius * 0.2)
|
||||
.startAngle(function (d) {
|
||||
return d.startAngle;
|
||||
}).endAngle(function (d) {
|
||||
@ -121,6 +133,7 @@
|
||||
that.donutGroups = that.canvas.set();
|
||||
|
||||
$(this.node).append(this.floatTag);
|
||||
|
||||
//添加透明效果
|
||||
var mouseOver = function () {
|
||||
floatTag.html('<div style="text-align:center; margin:auto; color:#ffffff">' + this.data('text') + '</div>');
|
||||
@ -155,17 +168,34 @@
|
||||
d.attr('fill-opacity', 1);
|
||||
});
|
||||
} else if (!this.data('click')) {
|
||||
|
||||
this.attr('fill-opacity', 0.5);
|
||||
}
|
||||
};
|
||||
|
||||
var mouseClick = function () {
|
||||
var index = this.data("donutIndex");
|
||||
var fan = groups[index];
|
||||
var flag = !this.data('click');
|
||||
this.data('click', flag);
|
||||
var a = 0.5 * ((that.groups[index].startAngle + that.groups[index].endAngle) - Math.PI);
|
||||
var nameX = conf.protrude * Math.cos(a);
|
||||
var nameY = conf.protrude * Math.sin(a);
|
||||
var ro = (fan.startAngle + fan.endAngle) * 90 / Math.PI;
|
||||
var angle = 0.5 * ((fan.startAngle + fan.endAngle) - Math.PI);
|
||||
var center = {
|
||||
x: ((conf.width - that.xOffset) / 2 + that.xOffset),
|
||||
y: conf.height / 2
|
||||
};
|
||||
var namePos = {
|
||||
x: conf.protrude * Math.cos(angle),
|
||||
y: conf.protrude * Math.sin(angle)
|
||||
};
|
||||
var radius = {
|
||||
x: conf.radius * Math.cos(angle) + namePos.x,
|
||||
y: conf.radius * Math.sin(angle) + namePos.y
|
||||
};
|
||||
var linePos = {
|
||||
x: 9 * Math.cos(angle),
|
||||
y: 9 * Math.sin(angle)
|
||||
};
|
||||
if (flag) {
|
||||
if (that.click === 0) {
|
||||
that.donutGroups.forEach(function (d) {
|
||||
@ -176,14 +206,28 @@
|
||||
}
|
||||
that.underBn[index].attr('opacity', 1).show();
|
||||
this.attr('fill-opacity', 1);
|
||||
this.data('nameTag').translate(0, - conf.protrude);
|
||||
this.data('line').translate(0, - conf.protrude);
|
||||
this.translate(nameX, nameY);
|
||||
this.data('nameTag').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + 2 * namePos.x) + " " + (center.y + radius.y + 2 * namePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
this.data('line').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + namePos.x - linePos.x) + " " + (center.y + radius.y + namePos.y - linePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
this.stop().animate({
|
||||
transform: "t" + (center.x + namePos.x) + " " + (center.y + namePos.y)
|
||||
}, conf.ms, conf.easing);
|
||||
//this.translate(nameX, nameY);
|
||||
that.click += 1;
|
||||
} else {
|
||||
this.data('nameTag').translate(0, conf.protrude);
|
||||
this.data('line').translate(0, conf.protrude);
|
||||
this.translate(-nameX, - nameY);
|
||||
this.data('nameTag').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + namePos.x) + " " + (center.y + radius.y + namePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
this.data('line').stop().animate({
|
||||
transform: "t" + (center.x + radius.x - linePos.x) + " " + (center.y + radius.y - linePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
this.stop().animate({
|
||||
transform: "t" + center.x + " " + center.y
|
||||
}, conf.ms, conf.easing);
|
||||
//this.translate(-nameX, - nameY);
|
||||
that.click -= 1;
|
||||
if (that.click > 0) {
|
||||
this.attr('fill-opacity', 0.5);
|
||||
@ -195,12 +239,13 @@
|
||||
var i;
|
||||
var nameStr;
|
||||
var nameX, nameY;
|
||||
var ro, a;
|
||||
var ro, angle;
|
||||
for (i = 0; i <= groups.length - 1; i++) {
|
||||
var fan = groups[i];
|
||||
//画外圈的pie图
|
||||
//计算每个group的path
|
||||
spline = pathCalc(groups[i]);
|
||||
tips = that.groupNames[i] + ": " + Math.round(groups[i].value) + " " + (groups[i].value * 100 / this.sum).toFixed(2) + "%";
|
||||
spline = pathCalc(fan);
|
||||
tips = fan.nameTag + ": " + Math.round(fan.value) + " " + (fan.value * 100 / this.sum).toFixed(2) + "%";
|
||||
|
||||
donutEle = that.canvas.path(spline)
|
||||
.translate((conf.width - this.xOffset) / 2 + this.xOffset, conf.height / 2)
|
||||
@ -215,15 +260,17 @@
|
||||
.click(mouseClick);
|
||||
|
||||
//每个donut上显示名称
|
||||
ro = (groups[i].startAngle + groups[i].endAngle) * 90 / Math.PI;
|
||||
a = 0.5 * ((groups[i].startAngle + groups[i].endAngle) - Math.PI);
|
||||
nameX = (conf.radius + 2 * conf.protrude) * Math.cos(a);
|
||||
nameY = (conf.radius + 2 * conf.protrude) * Math.sin(a);
|
||||
ro = (fan.startAngle + fan.endAngle) * 90 / Math.PI;
|
||||
angle = 0.5 * ((fan.startAngle + fan.endAngle) - Math.PI);
|
||||
nameX = (conf.radius + 2 * conf.protrude) * Math.cos(angle);
|
||||
nameY = (conf.radius + 2 * conf.protrude) * Math.sin(angle);
|
||||
nameStr = "T" + ((conf.width - that.xOffset) / 2 + that.xOffset) + "," + conf.height / 2 + "R" + ro + "T" + nameX + "," + nameY;
|
||||
|
||||
var line = that.canvas.path("M,0,-" + conf.protrude + "L0," + conf.protrude).transform(nameStr).translate(0, conf.protrude + 9);
|
||||
var nameTag = that.canvas.text().attr("font", "18px Verdana").attr("text", that.groupNames[i]).transform(nameStr);
|
||||
|
||||
var nameTag = that.canvas.text().attr({
|
||||
"font": "18px Verdana",
|
||||
"text": fan.nameTag
|
||||
}).translate(((conf.width - that.xOffset) / 2 + that.xOffset) + nameX, conf.height / 2 + nameY).rotate(ro); //transform(nameStr);
|
||||
donutEle.data('text', tips).data('click', false).data('nameTag', nameTag).data('line', line);
|
||||
that.donutGroups.push(donutEle);
|
||||
}
|
||||
@ -240,6 +287,7 @@
|
||||
var that = this;
|
||||
var conf = this.defaults;
|
||||
var paper = this.canvas;
|
||||
var groups = this.groups;
|
||||
var legendArea = this.legendArea;
|
||||
this.rectBn = paper.set();
|
||||
var rectBn = this.rectBn;
|
||||
@ -250,6 +298,7 @@
|
||||
underBn.push(paper.rect(legendArea[0] + 10, legendArea[1] + 10 + (20 + 3) * i, 180, 20).attr({
|
||||
"fill": "#ebebeb",
|
||||
"stroke": "none"
|
||||
//"r": 3
|
||||
}).hide());
|
||||
//色框
|
||||
paper.rect(legendArea[0] + 10 + 3, legendArea[1] + 10 + (20 + 3) * i + 6, 16, 8).attr({
|
||||
@ -257,7 +306,7 @@
|
||||
"stroke": "none"
|
||||
});
|
||||
//文字
|
||||
paper.text(legendArea[0] + 10 + 3 + 16 + 8, legendArea[1] + 10 + (20 + 3) * i + 10, this.groupNames[i]).attr({
|
||||
paper.text(legendArea[0] + 10 + 3 + 16 + 8, legendArea[1] + 10 + (20 + 3) * i + 10, this.groups[i].nameTag).attr({
|
||||
"fill": "black",
|
||||
"fill-opacity": 1,
|
||||
"font-family": "Verdana",
|
||||
@ -269,10 +318,12 @@
|
||||
"fill": "white",
|
||||
"fill-opacity": 0,
|
||||
"stroke": "none"
|
||||
//"r": 3
|
||||
}));
|
||||
}
|
||||
rectBn.forEach(function (d, i) {
|
||||
// TODO: 这里的事件建议采用事件委托
|
||||
var fan = groups[i];
|
||||
d.mouseover(function () {
|
||||
if (!that.donutGroups[i].data("click")) {
|
||||
underBn[i].attr('opacity', 0.5).show();
|
||||
@ -283,9 +334,24 @@
|
||||
}
|
||||
});
|
||||
d.click(function () {
|
||||
var a = 0.5 * ((that.groups[i].startAngle + that.groups[i].endAngle) - Math.PI);
|
||||
var nameX = conf.protrude * Math.cos(a);
|
||||
var nameY = conf.protrude * Math.sin(a);
|
||||
var ro = (fan.startAngle + fan.endAngle) * 90 / Math.PI;
|
||||
var angle = 0.5 * ((fan.startAngle + fan.endAngle) - Math.PI);
|
||||
var center = {
|
||||
x: ((conf.width - that.xOffset) / 2 + that.xOffset),
|
||||
y: conf.height / 2
|
||||
};
|
||||
var namePos = {
|
||||
x: conf.protrude * Math.cos(angle),
|
||||
y: conf.protrude * Math.sin(angle)
|
||||
};
|
||||
var radius = {
|
||||
x: conf.radius * Math.cos(angle) + namePos.x,
|
||||
y: conf.radius * Math.sin(angle) + namePos.y
|
||||
};
|
||||
var linePos = {
|
||||
x: 9 * Math.cos(angle),
|
||||
y: 9 * Math.sin(angle)
|
||||
};
|
||||
if (!that.donutGroups[i].data("click")) {
|
||||
if (that.click === 0) {
|
||||
that.donutGroups.forEach(function (d) {
|
||||
@ -296,14 +362,27 @@
|
||||
}
|
||||
underBn[i].attr('opacity', 1).show();
|
||||
that.donutGroups[i].data("click", true).attr('fill-opacity', 1);
|
||||
that.donutGroups[i].data('nameTag').translate(0, - conf.protrude);
|
||||
that.donutGroups[i].data('line').translate(0, - conf.protrude);
|
||||
that.donutGroups[i].translate(nameX, nameY);
|
||||
that.donutGroups[i].data('nameTag').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + 2 * namePos.x) + " " + (center.y + radius.y + 2 * namePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
that.donutGroups[i].data('line').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + namePos.x - linePos.x) + " " + (center.y + radius.y + namePos.y - linePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
that.donutGroups[i].stop().animate({
|
||||
transform: "t" + (center.x + namePos.x) + " " + (center.y + namePos.y)
|
||||
}, conf.ms, conf.easing);
|
||||
that.click += 1;
|
||||
|
||||
} else if (that.donutGroups[i].data("click")) {
|
||||
that.donutGroups[i].data('nameTag').translate(0, conf.protrude);
|
||||
that.donutGroups[i].data('line').translate(0, conf.protrude);
|
||||
that.donutGroups[i].translate(-nameX, - nameY);
|
||||
that.donutGroups[i].data('nameTag').stop().animate({
|
||||
transform: "t" + (center.x + radius.x + namePos.x) + " " + (center.y + radius.y + namePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
that.donutGroups[i].data('line').stop().animate({
|
||||
transform: "t" + (center.x + radius.x - linePos.x) + " " + (center.y + radius.y - linePos.y) + "r" + ro
|
||||
}, conf.ms, conf.easing);
|
||||
that.donutGroups[i].stop().animate({
|
||||
transform: "t" + center.x + " " + center.y
|
||||
}, conf.ms, conf.easing);
|
||||
that.click -= 1;
|
||||
if (that.click > 0) {
|
||||
that.donutGroups[i].attr('fill-opacity', 0.5);
|
||||
@ -314,6 +393,7 @@
|
||||
}
|
||||
underBn[i].hide();
|
||||
that.donutGroups[i].data("click", false);
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -336,22 +416,28 @@
|
||||
*/
|
||||
Pie.prototype.layout = function () {
|
||||
var that = this;
|
||||
|
||||
that.canvas.clear();
|
||||
var acc = 0;
|
||||
|
||||
this.sum = DataV.sum(this.groupValue);
|
||||
var sum = this.sum;
|
||||
this.groups = this.groupValue.map(function (item, index) {
|
||||
var startAngle = 2 * acc * Math.PI / sum;
|
||||
acc += item;
|
||||
var endAngle = 2 * acc * Math.PI / sum;
|
||||
var ret = {
|
||||
index: index,
|
||||
value: item,
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle
|
||||
nameTag: that.groupNames[index]
|
||||
};
|
||||
return ret;
|
||||
});
|
||||
this.groups = _.sortBy(that.groups, function (d) {
|
||||
return -d.value;
|
||||
});
|
||||
var acc = 0;
|
||||
this.groups.forEach(function (d) {
|
||||
d.startAngle = 2 * acc * Math.PI / sum;
|
||||
acc += d.value;
|
||||
d.endAngle = 2 * acc * Math.PI / sum;
|
||||
});
|
||||
};
|
||||
|
||||
return Pie;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user