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 * showlabel (number) : only show label if the value >= 'showlabel'% of total
35 * legend (array) : legend
36 * legendpos (string) : position of the legend ('right' / 'bottom')
37 * legendkeyshape (string) : shape of the legend keys ('circle' / 'rect')
38 * legendkeysize (number) : size of the legend keys (diameter for 'circle' and width for 'rect')
39 * legendfont (string) : font family of the legend labels
40 * legendfontsize (number) : font size of the legend labels
41 * legendfontcolor (string) : font color of the legend colors
42 * lineheight (number) : distance between two legend labels
43 * legendcolumn (number) : number of columns used to show legend (1 / 2)
46 function Piesectorchart(paper, width, height, cx, cy, r, values, opts) {
54 angle = opts.start_angle || 90,
57 labels = opts.labels || false, // default no labels
58 labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
59 labelSize = opts.labelsize || 18,
60 labelWeight = opts.labelweight || 'normal',
61 labelColor = opts.labelcolor || '#FFFFFF',
62 showLabel = typeof(opts.showlabel) != 'undefined' ? opts.showlabel : 5; // default show label if value >= 5% of total
64 opts.barwidth = opts.barwidth || 80;
66 paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
68 paper.customAttributes.sector = function (cx, cy, startAngle, endAngle, color, R) {
70 var rad = Math.PI / 180,
71 x1 = cx + r * Math.cos(-startAngle * rad),
72 x2 = cx + r * Math.cos(-endAngle * rad),
73 y1 = cy + r * Math.sin(-startAngle * rad),
74 y2 = cy + r * Math.sin(-endAngle * rad),
77 path = [["M", x1, y1], ["A", R, R, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2]];
79 return {path: path, stroke: color};
82 for (var i = 0; i < len; i++) {
83 total += values[i] * 1;
87 valueOf: function () { return this.value; }
92 paper.circle(cx, cy, r + opts.barwidth / 2).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0] || "#3E66BC", "stroke": "#fff" });
93 paper.circle(cx, cy, r - opts.barwidth / 2).attr({ fill: opts.background || "#F0F4F7", "stroke": "#fff" });
98 values.sort(function (a, b) {
99 return b.value - a.value;
103 for (i = 0; i < len; i++) {
106 values[cut].value += values[i];
107 values[cut].others = true;
110 // minimum degree of a pie shown
111 if (defcut && values[i] * 360 / total <= 1.5) {
117 len = Math.min(cut + 1, values.length);
121 for (i = 0; i < len; i++) {
124 "stroke-width": opts.barwidth
125 }).attr({sector: [cx, cy, a, a -= 360 * values[i] / total, opts.colors && opts.colors[i] || chartinst.colors[i], r]});
131 var rad = Math.PI / 180;
135 for (i = 0; i < len; i++) {
137 a -= 360 * values[i] / total;
139 // show the label only if the values >= 5% of total
140 if(labels && values[i] / total >= (showLabel / 100)) {
141 var text = labels[values[i].origin];
143 if(text.indexOf('#qty#') !== -1) {
144 text = text.replace('#qty#', Roo.util.Format.number(Math.round(values[i]), 0));
147 if(text.indexOf('#%#') !== -1) {
148 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
151 var tx = cx + r * Math.cos(-(a + 180 * values[i] / total) * rad),
152 ty = cy + r * Math.sin(-(a + 180 * values[i] / total) * rad);
154 paper.text(tx, ty, text).attr({
155 "font-size": labelSize,
156 "font-family": labelFont,
157 "font-weight" : labelWeight,
158 "text-anchor": "middle",
165 legend(paper, cx, cy, r, values, opts, total, len);
174 function legend(paper, cx, cy, r, values, opts, total, len)
176 var chartinst = this,
177 legendPos = opts.legendpos || 'right',
178 legendKeyShape = opts.legendkeyshape || 'circle',
179 legendKeySize = opts.legendkeysize || 12,
180 legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
181 legendFontSize = opts.legendfontsize || 18,
182 legendFontColor = opts.legendfontcolor || '#0C014F',
183 lineHeight = opts.lineheight || 30,
184 legendColumn = opts.legendcolumn || 1;
186 // default 'legendPos' is 'right'
187 // ix, iy: center position of legend key
188 var ix = cx + r + opts.barwidth / 2 + 30, // 30 pixels away from right of the chart
191 if(legendPos == 'bottom') {
192 ix = cx - r - opts.barwidth / 2 - 30; // 30 pixels away from left of the chart
193 iy = cy + r + opts.barwidth / 2 + 30; // 30 pixels away from bottom of the chart
195 // default 'legendColumn' is 1
196 if(legendColumn == 2) {
197 ix = cx - r - opts.barwidth / 2 - 90; // 90 pixels away from left of the chart
201 for (var i = 0; i < len; i++) {
203 if(legendKeyShape == 'rect') {
204 // pass top left position for 'rect'
205 paper.rect(ix - (legendKeySize / 2), iy - (legendKeySize / 2), legendKeySize, legendKeySize, 0).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
208 // pass center position for 'circle'
209 paper.circle(ix, iy, legendKeySize / 2).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
212 var text = (values[i].others) ? opts.others : opts.legend[values[i].origin] || values[i];
214 if(text.indexOf('#qty#') !== -1) {
215 text = text.replace('#qty#', Roo.util.Format.number(Math.round(values[i]), 0));
218 if(text.indexOf('#%#') !== -1) {
219 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
222 var ty = iy - legendFontSize / 10;
224 if(text.indexOf("\n")> -1) {
225 var ty = iy - legendFontSize / 10 + legendFontSize / 2;
228 // 12 pixels away from the right of legend key
229 // align legend key and text horizontally
230 paper.text(ix + legendKeySize / 2 + 12, ty, text).attr({
231 "font-size": legendFontSize,
232 "font-family": legendFont,
233 "text-anchor": "start",
234 fill : legendFontColor
237 if(legendColumn == 2) {
239 ix += r + opts.barwidth / 2 + 120;
243 ix -= r + opts.barwidth / 2 + 120;
252 var F = function() {};
253 F.prototype = Raphael.g;
254 Piesectorchart.prototype = new F;
257 Raphael.fn.piesectorchart = function(width, height, cx, cy, r, values, opts) {
258 return new Piesectorchart(this, width, height, cx, cy, r, values, opts);