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 * background (string) : background color
23 * start_angle (number) : the angle of the starting position of the first pie
24 * barwidth (number) : width of a pie
25 * colors (array) : colors of the pies
26 * cut (number) : after showing this number of elements using this number of pies, merge and show the rest of the elements using one pie (maximum 'cut' + 1 pies in total)
27 * others (string) : legend label labelling the pie for the merged elements (*required if there are merged elements)
28 * no_sort (boolean) : sort the values in descending order if it is not set
29 * labels (array) : labels on the pie
30 * labelfont (string) : font family of the labels
31 * labelsize (number) : font size of the labels
32 * labelweight (string)(number) : font weight of the labels
33 * labelcolor (string) : font color of the labels
34 * legend (array) : legend
35 * legendpos (string) : position of the legend ('right' / 'bottom')
36 * legendkeyshape (string) : shape of the legend keys ('circle' / 'rect')
37 * legendkeysize (number) : size of the legend keys (diameter for 'circle' and width for 'rect')
38 * legendfont (string) : font family of the legend labels
39 * legendfontsize (number) : font size of the legend labels
40 * legendfontcolor (string) : font color of the legend colors
41 * lineheight (number) : distance between two legend labels
42 * legendcolumn (number) : number of columns used to show legend (1 / 2)
45 function Piesectorchart(paper, width, height, cx, cy, r, values, opts) {
53 angle = opts.start_angle || 90,
56 labels = opts.labels || false, // default no labels
57 labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
58 labelSize = opts.labelsize || 18,
59 labelWeight = opts.labelweight || 'normal',
60 labelColor = opts.labelcolor || '#FFFFFF';
62 opts.barwidth = opts.barwidth || 80;
64 paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
66 paper.customAttributes.sector = function (cx, cy, startAngle, endAngle, color, R) {
68 var rad = Math.PI / 180,
69 x1 = cx + r * Math.cos(-startAngle * rad),
70 x2 = cx + r * Math.cos(-endAngle * rad),
71 y1 = cy + r * Math.sin(-startAngle * rad),
72 y2 = cy + r * Math.sin(-endAngle * rad),
75 path = [["M", x1, y1], ["A", R, R, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2]];
77 return {path: path, stroke: color};
80 for (var i = 0; i < len; i++) {
81 total += values[i] * 1;
85 valueOf: function () { return this.value; }
90 paper.circle(cx, cy, r + opts.barwidth / 2).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0] || "#3E66BC", "stroke": "#fff" });
91 paper.circle(cx, cy, r - opts.barwidth / 2).attr({ fill: opts.background || "#F0F4F7", "stroke": "#fff" });
96 values.sort(function (a, b) {
97 return b.value - a.value;
101 for (i = 0; i < len; i++) {
102 // minimum degree of a pie shown
103 if (defcut && values[i] * 360 / total <= 1.5) {
110 values[cut].value += values[i];
111 values[cut].others = true;
115 len = Math.min(cut + 1, values.length);
119 for (i = 0; i < len; i++) {
122 "stroke-width": opts.barwidth
123 }).attr({sector: [cx, cy, a, a -= 360 * values[i] / total, opts.colors && opts.colors[i] || chartinst.colors[i], r]});
129 var rad = Math.PI / 180;
133 for (i = 0; i < len; i++) {
135 a -= 360 * values[i] / total;
137 // show the label only if the values >= 5% of total
138 if(labels && values[i] / total >= 0.05) {
139 var text = labels[i];
141 if(text.indexOf('#qty#') !== -1) {
142 text = text.replace('#qty#', Math.round(values[i]));
145 if(text.indexOf('#%#') !== -1) {
146 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
149 var tx = cx + r * Math.cos(-(a + 180 * values[i] / total) * rad),
150 ty = cy + r * Math.sin(-(a + 180 * values[i] / total) * rad);
152 paper.text(tx, ty, text).attr({
153 "font-size": labelSize,
154 "font-family": labelFont,
155 "font-weight" : labelWeight,
156 "text-anchor": "middle",
163 legend(paper, cx, cy, r, values, opts, total, len);
172 function legend(paper, cx, cy, r, values, opts, total, len)
174 var legendPos = opts.legendpos || 'right',
175 legendKeyShape = opts.legendkeyshape || 'circle',
176 legendKeySize = opts.legendkeysize || 12,
177 legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
178 legendFontSize = opts.legendfontsize || 18,
179 legendFontColor = opts.legendfontcolor || '#0C014F',
180 lineHeight = opts.lineheight || 30,
181 legendColumn = opts.legendcolumn || 1;
183 // default 'legendPos' is 'right'
184 // ix, iy: center position of legend key
185 var ix = cx + r + opts.barwidth / 2 + 30, // 30 pixels away from right of the chart
188 if(legendPos == 'bottom') {
189 ix = cx - r - opts.barwidth / 2 - 30; // 30 pixels away from left of the chart
190 iy = cy + r + opts.barwidth / 2 + 30; // 30 pixels away from bottom of the chart
192 // default 'legendColumn' is 1
193 if(legendColumn == 2) {
194 ix = cx - r - opts.barwidth / 2 - 90; // 90 pixels away from left of the chart
198 for (var i = 0; i < len; i++) {
200 if(legendKeyShape == 'rect') {
201 // pass top left position for 'rect'
202 paper.rect(ix - (legendKeySize / 2), iy - (legendKeySize / 2), legendKeySize, legendKeySize, 0).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
205 // pass center position for 'circle'
206 paper.circle(ix, iy, legendKeySize / 2).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
209 var text = (values[i].others) ? opts.others : opts.legend[values[i].origin] || values[i];
211 if(text.indexOf('#qty#') !== -1) {
212 text = text.replace('#qty#', Math.round(values[i]));
215 if(text.indexOf('#%#') !== -1) {
216 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
219 var ty = iy - legendFontSize / 10;
221 if(text.indexOf("\n")> -1) {
222 var ty = iy - legendFontSize / 10 + legendFontSize / 2;
225 // 12 pixels away from the right of legend key
226 // align legend key and text horizontally
227 paper.text(ix + legendKeySize / 2 + 12, ty, text).attr({
228 "font-size": legendFontSize,
229 "font-family": legendFont,
230 "text-anchor": "start",
231 fill : legendFontColor
234 if(legendColumn == 2) {
236 ix += r + opts.barwidth / 2 + 120;
240 ix -= r + opts.barwidth / 2 + 120;
249 var F = function() {};
250 F.prototype = Raphael.g;
251 Piesectorchart.prototype = new F;
254 Raphael.fn.piesectorchart = function(width, height, cx, cy, r, values, opts) {
255 return new Piesectorchart(this, width, height, cx, cy, r, values, opts);