205 lines
No EOL
7.9 KiB
JavaScript
205 lines
No EOL
7.9 KiB
JavaScript
/*
|
|
* g.Raphael 0.4.1 - Charting library, based on Raphaël
|
|
*
|
|
* Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
|
|
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
|
|
*/
|
|
Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
|
|
opts = opts || {};
|
|
var paper = this,
|
|
sectors = [],
|
|
covers = this.set(),
|
|
chart = this.set(),
|
|
series = this.set(),
|
|
order = [],
|
|
len = values.length,
|
|
angle = 0,
|
|
total = 0,
|
|
others = 0,
|
|
cut = 9,
|
|
defcut = true;
|
|
chart.covers = covers;
|
|
if (len == 1) {
|
|
series.push(this.circle(cx, cy, r).attr({fill: this.g.colors[0], stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth}));
|
|
covers.push(this.circle(cx, cy, r).attr(this.g.shim));
|
|
total = values[0];
|
|
values[0] = {value: values[0], order: 0, valueOf: function () { return this.value; }};
|
|
series[0].middle = {x: cx, y: cy};
|
|
series[0].mangle = 180;
|
|
} else {
|
|
function sector(cx, cy, r, startAngle, endAngle, fill) {
|
|
var rad = Math.PI / 180,
|
|
x1 = cx + r * Math.cos(-startAngle * rad),
|
|
x2 = cx + r * Math.cos(-endAngle * rad),
|
|
xm = cx + r / 2 * Math.cos(-(startAngle + (endAngle - startAngle) / 2) * rad),
|
|
y1 = cy + r * Math.sin(-startAngle * rad),
|
|
y2 = cy + r * Math.sin(-endAngle * rad),
|
|
ym = cy + r / 2 * Math.sin(-(startAngle + (endAngle - startAngle) / 2) * rad),
|
|
res = ["M", cx, cy, "L", x1, y1, "A", r, r, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2, "z"];
|
|
res.middle = {x: xm, y: ym};
|
|
return res;
|
|
}
|
|
for (var i = 0; i < len; i++) {
|
|
total += values[i];
|
|
values[i] = {value: values[i], order: i, valueOf: function () { return this.value; }};
|
|
}
|
|
values.sort(function (a, b) {
|
|
return b.value - a.value;
|
|
});
|
|
for (i = 0; i < len; i++) {
|
|
if (defcut && values[i] * 360 / total <= 1.5) {
|
|
cut = i;
|
|
defcut = false;
|
|
}
|
|
if (i > cut) {
|
|
defcut = false;
|
|
values[cut].value += values[i];
|
|
values[cut].others = true;
|
|
others = values[cut].value;
|
|
}
|
|
}
|
|
len = Math.min(cut + 1, values.length);
|
|
others && values.splice(len) && (values[cut].others = true);
|
|
for (i = 0; i < len; i++) {
|
|
var mangle = angle - 360 * values[i] / total / 2;
|
|
if (!i) {
|
|
angle = 90 - mangle;
|
|
mangle = angle - 360 * values[i] / total / 2;
|
|
}
|
|
if (opts.init) {
|
|
var ipath = sector(cx, cy, 1, angle, angle - 360 * values[i] / total).join(",");
|
|
}
|
|
var path = sector(cx, cy, r, angle, angle -= 360 * values[i] / total);
|
|
var p = this.path(opts.init ? ipath : path).attr({fill: opts.colors && opts.colors[i] || Raphael.getColor("#194c68") || "#666", stroke: opts.stroke || "#fff", "stroke-width": (opts.strokewidth == null ? 1 : opts.strokewidth), "stroke-linejoin": "round"});
|
|
p.value = values[i];
|
|
p.middle = path.middle;
|
|
p.mangle = mangle;
|
|
sectors.push(p);
|
|
series.push(p);
|
|
opts.init && p.animate({path: path.join(",")}, (+opts.init - 1) || 1000, ">");
|
|
}
|
|
for (i = 0; i < len; i++) {
|
|
p = paper.path(sectors[i].attr("path")).attr(this.g.shim);
|
|
opts.href && opts.href[i] && p.attr({href: opts.href[i]});
|
|
p.attr = function () {};
|
|
covers.push(p);
|
|
series.push(p);
|
|
}
|
|
}
|
|
|
|
chart.hover = function (fin, fout) {
|
|
fout = fout || function () {};
|
|
var that = this;
|
|
for (var i = 0; i < len; i++) {
|
|
(function (sector, cover, j) {
|
|
var o = {
|
|
sector: sector,
|
|
cover: cover,
|
|
cx: cx,
|
|
cy: cy,
|
|
mx: sector.middle.x,
|
|
my: sector.middle.y,
|
|
mangle: sector.mangle,
|
|
r: r,
|
|
value: values[j],
|
|
total: total,
|
|
label: that.labels && that.labels[j]
|
|
};
|
|
cover.mouseover(function () {
|
|
fin.call(o);
|
|
}).mouseout(function () {
|
|
fout.call(o);
|
|
});
|
|
})(series[i], covers[i], i);
|
|
}
|
|
return this;
|
|
};
|
|
// x: where label could be put
|
|
// y: where label could be put
|
|
// value: value to show
|
|
// total: total number to count %
|
|
chart.each = function (f) {
|
|
var that = this;
|
|
for (var i = 0; i < len; i++) {
|
|
(function (sector, cover, j) {
|
|
var o = {
|
|
sector: sector,
|
|
cover: cover,
|
|
cx: cx,
|
|
cy: cy,
|
|
x: sector.middle.x,
|
|
y: sector.middle.y,
|
|
mangle: sector.mangle,
|
|
r: r,
|
|
value: values[j],
|
|
total: total,
|
|
label: that.labels && that.labels[j]
|
|
};
|
|
f.call(o);
|
|
})(series[i], covers[i], i);
|
|
}
|
|
return this;
|
|
};
|
|
chart.click = function (f) {
|
|
var that = this;
|
|
for (var i = 0; i < len; i++) {
|
|
(function (sector, cover, j) {
|
|
var o = {
|
|
sector: sector,
|
|
cover: cover,
|
|
cx: cx,
|
|
cy: cy,
|
|
mx: sector.middle.x,
|
|
my: sector.middle.y,
|
|
mangle: sector.mangle,
|
|
r: r,
|
|
value: values[j],
|
|
total: total,
|
|
label: that.labels && that.labels[j]
|
|
};
|
|
cover.click(function () { f.call(o); });
|
|
})(series[i], covers[i], i);
|
|
}
|
|
return this;
|
|
};
|
|
chart.inject = function (element) {
|
|
element.insertBefore(covers[0]);
|
|
};
|
|
var legend = function (labels, otherslabel, mark, dir) {
|
|
var x = cx + r + r / 5,
|
|
y = cy,
|
|
h = y + 10;
|
|
labels = labels || [];
|
|
dir = (dir && dir.toLowerCase && dir.toLowerCase()) || "east";
|
|
mark = paper.g.markers[mark && mark.toLowerCase()] || "disc";
|
|
chart.labels = paper.set();
|
|
for (var i = 0; i < len; i++) {
|
|
var clr = series[i].attr("fill"),
|
|
j = values[i].order,
|
|
txt;
|
|
values[i].others && (labels[j] = otherslabel || "Others");
|
|
labels[j] = paper.g.labelise(labels[j], values[i], total);
|
|
chart.labels.push(paper.set());
|
|
chart.labels[i].push(paper.g[mark](x + 5, h, 5).attr({fill: clr, stroke: "none"}));
|
|
chart.labels[i].push(txt = paper.text(x + 20, h, labels[j] || values[j]).attr(paper.g.txtattr).attr({fill: opts.legendcolor || "#000", "text-anchor": "start"}));
|
|
covers[i].label = chart.labels[i];
|
|
h += txt.getBBox().height * 1.2;
|
|
}
|
|
var bb = chart.labels.getBBox(),
|
|
tr = {
|
|
east: [0, -bb.height / 2],
|
|
west: [-bb.width - 2 * r - 20, -bb.height / 2],
|
|
north: [-r - bb.width / 2, -r - bb.height - 10],
|
|
south: [-r - bb.width / 2, r + 10]
|
|
}[dir];
|
|
chart.labels.translate.apply(chart.labels, tr);
|
|
chart.push(chart.labels);
|
|
};
|
|
if (opts.legend) {
|
|
legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos);
|
|
}
|
|
chart.push(series, covers);
|
|
chart.series = series;
|
|
chart.covers = covers;
|
|
return chart;
|
|
}; |