2 * g.Raphael 0.5 - Charting library, based on Raphaƫl
4 * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
5 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
7 Raphael = typeof(Raphael) != 'undefined' ? Raphael : (imports ? imports.seed.Raphael.Raphael : {});
8 Roo = typeof(Roo) != 'undefined' ? Roo: (imports ? imports.seed.Roo.Roo: {});
9 //chartinst = typeof(chartinst) != 'undefined' ? chartinst: (imports ? imports.chartinst.chartinst : {});
16 * @param {Raphael} paper to draw on
17 * @param {int} cx - centre X
18 * @param {int} cy - centre Y
19 * @param {int} r - radius
20 * @param {Array} values
21 * @param {Object} opts options
22 * cut : after this meany items - do not show a pie element?
28 function Piechart(paper, cx, cy, r, values, opts) {
45 function sector(cx, cy, r, startAngle, endAngle, fill) {
46 Roo.log([startAngle, endAngle]);
49 var rad = Math.PI / 180,
50 x1 = cx + r * Math.cos(-startAngle * rad),
51 x2 = cx + r * Math.cos(-endAngle * rad),
52 xm = cx + r / 2 * Math.cos(-(startAngle + (endAngle - startAngle) / 2) * rad),
53 y1 = cy + r * Math.sin(-startAngle * rad),
54 y2 = cy + r * Math.sin(-endAngle * rad),
55 ym = cy + r / 2 * Math.sin(-(startAngle + (endAngle - startAngle) / 2) * rad),
59 "A", r, r, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2,
63 res.middle = { x: xm, y: ym };
67 chart.covers = covers;
70 series.push(paper.circle(cx, cy, r).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0] || "#666", stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth }));
71 covers.push(paper.circle(cx, cy, r).attr(chartinst.shim));
72 total = values[0] * 1;
73 values[0] = { value: values[0], order: 0, valueOf: function () { return this.value; } };
74 series[0].middle = {x: cx, y: cy};
75 series[0].mangle = 180;
77 for (var i = 0; i < len; i++) {
78 total += values[i] * 1;
82 valueOf: function () { return this.value; }
87 values.sort(function (a, b) {
88 return b.value - a.value;
91 for (i = 0; i < len; i++) {
92 if (defcut && values[i] * 360 / total <= 1.5) {
99 values[cut].value += values[i];
100 values[cut].others = true;
101 others = values[cut].value;
105 len = Math.min(cut + 1, values.length);
106 others && values.splice(len) && (values[cut].others = true);
108 for (i = 0; i < len; i++) {
109 var mangle = angle - 360 * values[i] / total / 2;
113 if (typeof(opts.start_angle) == 'undefined') {
116 angle = opts.start_angle;
119 //Roo.log('start angle: ' + angle);
120 mangle = angle - 360 * values[i] / total / 2;
124 var ipath = sector(cx, cy, 1, angle, angle - 360 * values[i] / total).join(",");
127 var path = sector(cx, cy, r, angle, angle -= 360 * values[i] / total);
131 Roo.log(angle- 360 * values[i] / total);
133 var p = paper.path(opts.init ? ipath : path).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#666", stroke: opts.stroke || "#fff", "stroke-width": (opts.strokewidth == null ? 1 : opts.strokewidth), "stroke-linejoin": "round" });
136 p.middle = path.middle;
140 opts.init && p.animate({ path: path.join(",") }, (+opts.init - 1) || 1000, ">");
143 for (i = 0; i < len; i++) {
144 p = paper.path(sectors[i].attr("path")).attr(chartinst.shim);
145 opts.href && opts.href[i] && p.attr({ href: opts.href[i] });
146 p.attr = function () {};
152 chart.hover = function (fin, fout) {
153 fout = fout || function () {};
157 for (var i = 0; i < len; i++) {
158 (function (sector, cover, j) {
166 mangle: sector.mangle,
171 label: that.labels && that.labels[j]
173 cover.mouseover(function () {
175 }).mouseout(function () {
178 })(series[i], covers[i], i);
183 // x: where label could be put
184 // y: where label could be put
185 // value: value to show
186 // total: total number to count %
187 chart.each = function (f) {
190 for (var i = 0; i < len; i++) {
191 (function (sector, cover, j) {
199 mangle: sector.mangle,
204 label: that.labels && that.labels[j]
207 })(series[i], covers[i], i);
212 chart.click = function (f) {
215 for (var i = 0; i < len; i++) {
216 (function (sector, cover, j) {
224 mangle: sector.mangle,
229 label: that.labels && that.labels[j]
231 cover.click(function () { f.call(o); });
232 })(series[i], covers[i], i);
237 chart.inject = function (element) {
238 element.insertBefore(covers[0]);
241 var legend = function (labels, otherslabel, mark, dir) {
242 var x = cx + r + r / 5,
246 labels = labels || [];
247 dir = (dir && dir.toLowerCase && dir.toLowerCase()) || "east";
248 mark = paper[mark && mark.toLowerCase()] || "circle";
249 chart.labels = paper.set();
251 for (var i = 0; i < len; i++) {
252 var clr = series[i].attr("fill"),
256 values[i].others && (labels[j] = otherslabel || "Others");
257 labels[j] = chartinst.labelise(labels[j], values[i], total);
258 chart.labels.push(paper.set());
259 chart.labels[i].push(paper[mark](x + 5, h, 5).attr({ fill: clr, stroke: "none" }));
260 chart.labels[i].push(
261 txt = paper.text(x + 20, h, labels[j] || values[j]).attr(chartinst.txtattr).attr({ fill: opts.legendcolor || "#000", "text-anchor": "start"}));
262 covers[i].label = chart.labels[i];
263 // Roo.log(JSON.stringify(txt.getBBox()));
264 h += txt.getBBox().height * 1.2;
267 var bb = chart.labels.getBBox(),
269 east: [0, -bb.height / 2],
270 west: [-bb.width - 2 * r - 20, -bb.height / 2],
271 north: [-r - bb.width / 2, -r - bb.height - 10],
272 south: [-r - bb.width / 2, r + 10]
275 chart.labels.translate.apply(chart.labels, tr);
276 chart.push(chart.labels);
280 legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos);
283 chart.push(series, covers);
284 chart.series = series;
285 chart.covers = covers;
287 chart.sector = sector;
295 var F = function() {};
296 F.prototype = Raphael.g;
297 Piechart.prototype = new F;
300 Raphael.fn.piechart = function(cx, cy, r, values, opts) {
301 return new Piechart(this, cx, cy, r, values, opts);