rgraph-rails 4.62 → 4.64

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -4
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/RGraph.bar.js +240 -3742
  5. data/vendor/assets/javascripts/RGraph.bipolar.js +165 -2005
  6. data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -395
  7. data/vendor/assets/javascripts/RGraph.common.context.js +30 -595
  8. data/vendor/assets/javascripts/RGraph.common.core.js +418 -5359
  9. data/vendor/assets/javascripts/RGraph.common.csv.js +20 -276
  10. data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -450
  11. data/vendor/assets/javascripts/RGraph.common.dynamic.js +88 -1395
  12. data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1545
  13. data/vendor/assets/javascripts/RGraph.common.key.js +52 -753
  14. data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -563
  15. data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -352
  16. data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -450
  17. data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -219
  18. data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +34 -570
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +33 -544
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +51 -755
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +37 -645
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +36 -633
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +35 -514
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +37 -559
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +33 -548
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +36 -664
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -812
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
  30. data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
  31. data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
  32. data/vendor/assets/javascripts/RGraph.gantt.js +77 -1354
  33. data/vendor/assets/javascripts/RGraph.gauge.js +85 -1421
  34. data/vendor/assets/javascripts/RGraph.hbar.js +162 -2788
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1401
  36. data/vendor/assets/javascripts/RGraph.line.js +249 -4248
  37. data/vendor/assets/javascripts/RGraph.meter.js +74 -1280
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +19 -301
  39. data/vendor/assets/javascripts/RGraph.odo.js +71 -1264
  40. data/vendor/assets/javascripts/RGraph.pie.js +137 -2288
  41. data/vendor/assets/javascripts/RGraph.radar.js +110 -1847
  42. data/vendor/assets/javascripts/RGraph.rose.js +108 -1977
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +80 -1432
  44. data/vendor/assets/javascripts/RGraph.scatter.js +172 -3163
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +60 -1120
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +66 -1735
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +21 -246
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +255 -3937
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +20 -276
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +68 -1303
  51. data/vendor/assets/javascripts/RGraph.svg.common.key.js +19 -205
  52. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +29 -352
  53. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +22 -273
  54. data/vendor/assets/javascripts/RGraph.svg.funnel.js +32 -0
  55. data/vendor/assets/javascripts/RGraph.svg.hbar.js +59 -1400
  56. data/vendor/assets/javascripts/RGraph.svg.line.js +70 -1580
  57. data/vendor/assets/javascripts/RGraph.svg.pie.js +55 -1131
  58. data/vendor/assets/javascripts/RGraph.svg.radar.js +57 -1502
  59. data/vendor/assets/javascripts/RGraph.svg.rose.js +66 -1817
  60. data/vendor/assets/javascripts/RGraph.svg.scatter.js +58 -1261
  61. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +28 -865
  62. data/vendor/assets/javascripts/RGraph.svg.waterfall.js +45 -1252
  63. data/vendor/assets/javascripts/RGraph.thermometer.js +63 -1136
  64. data/vendor/assets/javascripts/RGraph.vprogress.js +83 -1470
  65. data/vendor/assets/javascripts/RGraph.waterfall.js +83 -1347
  66. metadata +5 -4
  67. data/vendor/assets/javascripts/financial-data.js +0 -1067
@@ -1,2289 +1,138 @@
1
- // version: 2017-05-08
2
- /**
3
- * o--------------------------------------------------------------------------------o
4
- * | This file is part of the RGraph package - you can learn more at: |
5
- * | |
6
- * | http://www.rgraph.net |
7
- * | |
8
- * | RGraph is licensed under the Open Source MIT license. That means that it's |
9
- * | totally free to use! |
10
- * o--------------------------------------------------------------------------------o
11
- */
12
1
 
13
- RGraph = window.RGraph || {isRGraph: true};
14
-
15
- /**
16
- * The pie chart constructor
17
- *
18
- * @param data array The data to be represented on the Pie chart
19
- */
20
- RGraph.Pie = function (conf)
21
- {
22
- /**
23
- * Allow for object config style
24
- */
25
- if ( typeof conf === 'object'
26
- && typeof conf.data === 'object'
27
- && typeof conf.id === 'string') {
28
-
29
- var id = conf.id,
30
- canvas = document.getElementById(id),
31
- data = conf.data,
32
- parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor
33
-
34
- } else {
35
-
36
- var id = conf,
37
- canvas = document.getElementById(id),
38
- data = arguments[1];
39
- }
40
-
41
-
42
-
43
-
44
- // Get the canvas and context objects
45
- this.id = id;
46
- this.canvas = canvas;
47
- this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
48
- this.canvas.__object__ = this;
49
- this.total = 0;
50
- this.subTotal = 0;
51
- this.angles = [];
52
- this.data = data;
53
- this.properties = [];
54
- this.type = 'pie';
55
- this.isRGraph = true;
56
- this.coords = [];
57
- this.coords.key = [];
58
- this.coordsSticks = [];
59
- this.coordsText = [];
60
- this.uid = RGraph.CreateUID();
61
- this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
62
- this.colorsParsed = false;
63
- this.original_colors = [];
64
- this.firstDraw = true; // After the first draw this will be false
65
- this.exploding = null;
66
-
67
-
68
- //
69
- // Go through the data and convert strings to numbers
70
- //
71
- for (var i=0; i<this.data.length; ++i) {
72
- if (typeof this.data[i] === 'string') {
73
- this.data[i] = parseFloat(this.data[i]);
74
- }
75
- }
76
-
77
- this.properties =
78
- {
79
- 'chart.centerx.adjust': 0,
80
- 'chart.centery.adjust': 0,
81
- 'chart.colors': ['red', '#ccc', '#cfc', 'blue', 'pink', 'yellow', 'black', 'orange', 'cyan', 'purple', '#78CAEA', '#E284E9', 'white', 'blue', '#9E7BF6'],
82
- 'chart.strokestyle': 'white',
83
- 'chart.linewidth': 3,
84
- 'chart.labels': [],
85
- 'chart.labels.bold': false,
86
- 'chart.labels.sticks': false,
87
- 'chart.labels.sticks.length': 7,
88
- 'chart.labels.sticks.colors': null,
89
- 'chart.labels.sticks.usecolors': true,
90
- 'chart.labels.sticks.linewidth': 1,
91
- 'chart.labels.sticks.hlength': 5,
92
- 'chart.labels.sticks.list': false,
93
- 'chart.labels.ingraph': null,
94
- 'chart.labels.ingraph.color': null,
95
- 'chart.labels.ingraph.font': null,
96
- 'chart.labels.ingraph.size': null,
97
- 'chart.labels.ingraph.bounding':true,
98
- 'chart.labels.ingraph.bounding.fill':'white',
99
- 'chart.labels.ingraph.specific':null,
100
- 'chart.labels.ingraph.units.pre':'',
101
- 'chart.labels.ingraph.units.post':'',
102
- 'chart.labels.ingraph.radius': null,
103
- 'chart.labels.center': null,
104
- 'chart.labels.center.size': 26,
105
- 'chart.labels.center.font': 'Segoe UI, Arial, Verdana, sans-serif',
106
- 'chart.labels.center.color': 'black',
107
- 'chart.labels.center.italic': false,
108
- 'chart.labels.center.bold': false,
109
- 'chart.labels.center.units.pre': '',
110
- 'chart.labels.center.units.post': '',
111
- 'chart.gutter.left': 25,
112
- 'chart.gutter.right': 25,
113
- 'chart.gutter.top': 25,
114
- 'chart.gutter.bottom': 25,
115
- 'chart.title': '',
116
- 'chart.title.background': null,
117
- 'chart.title.hpos': null,
118
- 'chart.title.vpos': 0.5,
119
- 'chart.title.bold': true,
120
- 'chart.title.font': null,
121
- 'chart.title.x': null,
122
- 'chart.title.y': null,
123
- 'chart.title.halign': null,
124
- 'chart.title.valign': null,
125
- 'chart.shadow': true,
126
- 'chart.shadow.color': '#aaa',
127
- 'chart.shadow.offsetx': 0,
128
- 'chart.shadow.offsety': 0,
129
- 'chart.shadow.blur': 15,
130
- 'chart.text.size': 12,
131
- 'chart.text.color': 'black',
132
- 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
133
- 'chart.text.accessible': true,
134
- 'chart.text.accessible.overflow': 'visible',
135
- 'chart.text.accessible.pointerevents': true,
136
- 'chart.contextmenu': null,
137
- 'chart.tooltips': null,
138
- 'chart.tooltips.event': 'onclick',
139
- 'chart.tooltips.effect': 'fade',
140
- 'chart.tooltips.css.class': 'RGraph_tooltip',
141
- 'chart.tooltips.highlight': true,
142
- 'chart.highlight.style': '2d',
143
- 'chart.highlight.style.twod.fill': 'rgba(255,255,255,0.7)',
144
- 'chart.highlight.style.twod.stroke': 'rgba(255,255,255,0.7)',
145
- 'chart.highlight.style.outline.width': null,
146
- 'chart.centerx': null,
147
- 'chart.centery': null,
148
- 'chart.radius': null,
149
- 'chart.border': false,
150
- 'chart.border.color': 'rgba(255,255,255,0.5)',
151
- 'chart.key': null,
152
- 'chart.key.background': 'white',
153
- 'chart.key.position': 'graph',
154
- 'chart.key.halign': 'right',
155
- 'chart.key.shadow': false,
156
- 'chart.key.shadow.color': '#666',
157
- 'chart.key.shadow.blur': 3,
158
- 'chart.key.shadow.offsetx': 2,
159
- 'chart.key.shadow.offsety': 2,
160
- 'chart.key.position.gutter.boxed': false,
161
- 'chart.key.position.x': null,
162
- 'chart.key.position.y': null,
163
- 'chart.key.color.shape': 'square',
164
- 'chart.key.rounded': true,
165
- 'chart.key.linewidth': 1,
166
- 'chart.key.colors': null,
167
- 'chart.key.interactive': false,
168
- 'chart.key.interactive.highlight.chart.stroke': 'black',
169
- 'chart.key.interactive.highlight.chart.fill': 'rgba(255,255,255,0.7)',
170
- 'chart.key.interactive.highlight.label': 'rgba(255,0,0,0.2)',
171
- 'chart.key.text.color': 'black',
172
- 'chart.annotatable': false,
173
- 'chart.annotate.color': 'black',
174
- 'chart.zoom.factor': 1.5,
175
- 'chart.zoom.fade.in': true,
176
- 'chart.zoom.fade.out': true,
177
- 'chart.zoom.hdir': 'right',
178
- 'chart.zoom.vdir': 'down',
179
- 'chart.zoom.frames': 25,
180
- 'chart.zoom.delay': 16.666,
181
- 'chart.zoom.shadow': true,
182
- 'chart.zoom.background': true,
183
- 'chart.zoom.action': 'zoom',
184
- 'chart.resizable': false,
185
- 'chart.resize.handle.adjust': [0,0],
186
- 'chart.resize.handle.background': null,
187
- 'chart.variant': 'pie',
188
- 'chart.variant.donut.width': null,
189
- 'chart.variant.threed.depth': 20,
190
- 'chart.exploded': [],
191
- 'chart.effect.roundrobin.multiplier': 1,
192
- 'chart.events.click': null,
193
- 'chart.events.mousemove': null,
194
- 'chart.centerpin': null,
195
- 'chart.centerpin.fill': 'gray',
196
- 'chart.centerpin.stroke': 'white',
197
- 'chart.origin': 0 - (Math.PI / 2),
198
- 'chart.events': true,
199
- 'chart.labels.colors': [],
200
- 'chart.clearto': 'rgba(0,0,0,0)'
201
- }
202
-
203
-
204
-
205
- /**
206
- * Calculate the total
207
- */
208
- for (var i=0,len=data.length; i<len; i++) {
209
- this.total += data[i];
210
-
211
- // This loop also creates the $xxx objects - this isn't related to
212
- // the code above but just saves doing another loop through the data
213
- this['$' + i] = {};
214
- }
215
-
216
-
217
- /**
218
- * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
219
- * done already
220
- */
221
- if (!this.canvas.__rgraph_aa_translated__) {
222
- this.context.translate(0.5,0.5);
223
-
224
- this.canvas.__rgraph_aa_translated__ = true;
225
- }
226
-
227
-
228
-
229
-
230
- // Short variable names
231
- var RG = RGraph,
232
- ca = this.canvas,
233
- co = ca.getContext('2d'),
234
- prop = this.properties,
235
- pa2 = RG.path2,
236
- win = window,
237
- doc = document,
238
- ma = Math
239
-
240
-
241
-
242
- /**
243
- * "Decorate" the object with the generic effects if the effects library has been included
244
- */
245
- if (RG.Effects && typeof RG.Effects.decorate === 'function') {
246
- RG.Effects.decorate(this);
247
- }
248
-
249
-
250
-
251
-
252
- /**
253
- * A generic setter
254
- */
255
- this.set =
256
- this.Set = function (name)
257
- {
258
- var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
259
-
260
- /**
261
- * the number of arguments is only one and it's an
262
- * object - parse it for configuration data and return.
263
- */
264
- if (arguments.length === 1 && typeof name === 'object') {
265
- RG.parseObjectStyleConfig(this, name);
266
- return this;
267
- }
268
-
269
-
270
-
271
-
272
-
273
- /**
274
- * This should be done first - prepend the property name with "chart." if necessary
275
- */
276
- if (name.substr(0,6) != 'chart.') {
277
- name = 'chart.' + name;
278
- }
279
-
280
-
281
-
282
-
283
- // Convert uppercase letters to dot+lower case letter
284
- while(name.match(/([A-Z])/)) {
285
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
286
- }
287
-
288
-
289
-
290
- if (name == 'chart.highlight.style.twod.color') {
291
- name = 'chart.highlight.style.twod.fill';
292
- }
293
-
294
-
295
- if (name == 'chart.labels.spaced') {
296
- name = 'chart.labels.sticks.list';
297
- }
298
-
299
-
300
-
301
-
302
-
303
-
304
- prop[name] = value;
305
-
306
- return this;
307
- };
308
-
309
-
310
-
311
-
312
- /**
313
- * A generic getter
314
- */
315
- this.get =
316
- this.Get = function (name)
317
- {
318
- /**
319
- * This should be done first - prepend the property name with "chart." if necessary
320
- */
321
- if (name.substr(0,6) != 'chart.') {
322
- name = 'chart.' + name;
323
- }
324
-
325
- // Convert uppercase letters to dot+lower case letter
326
- while(name.match(/([A-Z])/)) {
327
- name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
328
- }
329
-
330
- if (name == 'chart.highlight.style.twod.color') {
331
- name = 'chart.highlight.style.twod.fill';
332
- }
333
-
334
- return prop[name];
335
- };
336
-
337
-
338
-
339
-
340
- /**
341
- * This draws the pie chart
342
- */
343
- this.draw =
344
- this.Draw = function ()
345
- {
346
- /**
347
- * Fire the onbeforedraw event
348
- */
349
- RG.FireCustomEvent(this, 'onbeforedraw');
350
-
351
- // NB: Colors are parsed further down so that the center X/Y can be used
352
-
353
-
354
- /**
355
- * This is new in May 2011 and facilitates indiviual gutter settings,
356
- * eg chart.gutter.left
357
- */
358
- this.gutterLeft = prop['chart.gutter.left'];
359
- this.gutterRight = prop['chart.gutter.right'];
360
- this.gutterTop = prop['chart.gutter.top'];
361
- this.gutterBottom = prop['chart.gutter.bottom'];
362
-
363
- this.radius = this.getRadius();// MUST be first
364
- this.centerx = (this.graph.width / 2) + this.gutterLeft + prop['chart.centerx.adjust'];
365
- this.centery = (this.graph.height / 2) + this.gutterTop + prop['chart.centery.adjust'];
366
- this.subTotal = this.properties['chart.origin'];
367
- this.angles = [];
368
- this.coordsText = [];
369
-
370
- /**
371
- * Allow specification of a custom radius & center X/Y
372
- */
373
- if (typeof prop['chart.radius'] === 'number') this.radius = prop['chart.radius'];
374
- if (typeof prop['chart.centerx'] === 'number') this.centerx = prop['chart.centerx'];
375
- if (typeof prop['chart.centery'] === 'number') this.centery = prop['chart.centery'];
376
-
377
-
378
- if (this.radius <= 0) {
379
- return;
380
- }
381
-
382
- /**
383
- * Parse the colors for gradients. Its down here so that the center X/Y can be used
384
- */
385
- if (!this.colorsParsed) {
386
-
387
- this.parseColors();
388
-
389
- // Don't want to do this again
390
- this.colorsParsed = true;
391
- }
392
-
393
-
394
-
395
-
396
- /**
397
- * This sets the label colors. Doing it here saves lots of if() conditions in the draw method
398
- */
399
- if (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
400
- while (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
401
- prop['chart.labels.colors'].push(prop['chart.labels.colors'][prop['chart.labels.colors'].length - 1]);
402
- }
403
- } else {
404
- if (typeof prop['chart.labels.colors'] === 'undefined') {
405
- prop['chart.labels.colors'] = [];
406
- }
407
-
408
- while (prop['chart.labels.colors'].length < prop['chart.labels'].length) {
409
- prop['chart.labels.colors'].push(prop['chart.text.color']);
410
- }
411
- }
412
-
413
-
414
-
415
-
416
- if (prop['chart.variant'].indexOf('3d') > 0) {
417
- return this.draw3d();
418
- }
419
-
420
-
421
-
422
-
423
- /**
424
- * Draw the title
425
- */
426
- RG.DrawTitle(
427
- this,
428
- prop['chart.title'],
429
- (ca.height / 2) - this.radius - 5,
430
- this.centerx,
431
- prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
432
- );
433
-
434
- /**
435
- * Draw the shadow if required
436
- *
437
- * ???
438
- */
439
- //if (prop['chart.shadow'] && false) {
440
- //
441
- // var offsetx = doc.all ? prop['chart.shadow.offsetx'] : 0;
442
- // var offsety = doc.all ? prop['chart.shadow.offsety'] : 0;
443
- //
444
- // co.beginPath();
445
- // co.fillStyle = prop['chart.shadow.color'];
446
- //
447
- // co.shadowColor = prop['chart.shadow.color'];
448
- // co.shadowBlur = prop['chart.shadow.blur'];
449
- // co.shadowOffsetX = prop['chart.shadow.offsetx'];
450
- // co.shadowOffsetY = prop['chart.shadow.offsety'];
451
- //
452
- // co.arc(this.centerx + offsetx, this.centery + offsety, this.radius, 0, TWOPI, 0);
453
- //
454
- // co.fill();
455
- //
456
- // // Now turn off the shadow
457
- // RG.NoShadow(this);
458
- //}
459
-
460
- /**
461
- * The total of the array of values
462
- */
463
- this.total = RG.array_sum(this.data);
464
- var tot = this.total;
465
- var data = this.data;
466
-
467
- for (var i=0,len=this.data.length; i<len; i++) {
468
-
469
- var angle = ((data[i] / tot) * RG.TWOPI);
470
-
471
- // Draw the segment
472
- this.DrawSegment(angle,prop['chart.colors'][i],i == (len - 1), i);
473
- }
474
-
475
- RG.NoShadow(this);
476
-
477
- /**
478
- * Redraw the seperating lines
479
- */
480
- if (prop['chart.linewidth'] > 0) {
481
- this.DrawBorders();
482
- }
483
-
484
- /**
485
- * Now draw the segments again with shadow turned off. This is always performed,
486
- * not just if the shadow is on.
487
- */
488
- var len = this.angles.length;
489
- var r = this.radius;
490
-
491
-
492
- for (var action=0; action<2; action+=1) {
493
- for (var i=0; i<len; i++) {
494
-
495
- co.beginPath();
496
-
497
- var segment = this.angles[i];
498
-
499
- if (action === 1) {
500
- co.strokeStyle = typeof(prop['chart.strokestyle']) == 'object' ? prop['chart.strokestyle'][i] : prop['chart.strokestyle'];
501
- }
502
- prop['chart.colors'][i] ? co.fillStyle = prop['chart.colors'][i] : null;
503
- co.lineJoin = 'round';
504
-
505
- co.arc(segment[2],
506
- segment[3],
507
- r,
508
- (segment[0]),
509
- (segment[1]),
510
- false);
511
- if (prop['chart.variant'] == 'donut') {
512
-
513
- co.arc(
514
- segment[2],
515
- segment[3],
516
- typeof(prop['chart.variant.donut.width']) == 'number' ? r - prop['chart.variant.donut.width'] : r / 2,
517
- (segment[1]),
518
- (segment[0]),
519
- true
520
- );
521
-
522
- } else {
523
- co.lineTo(segment[2], segment[3]);
524
- }
525
- co.closePath();
526
- action === 0 ? co.fill() : co.stroke();
527
- }
528
- }
529
-
530
-
531
-
532
-
533
- /**
534
- * Draw label sticks
535
- */
536
- if (prop['chart.labels.sticks']) {
537
-
538
- this.DrawSticks();
539
-
540
- // Redraw the border going around the Pie chart if the stroke style is NOT white
541
- var strokeStyle = prop['chart.strokestyle'];
542
- }
543
-
544
- /**
545
- * Draw the labels
546
- */
547
- if (prop['chart.labels']) {
548
- this.DrawLabels();
549
- }
550
-
551
-
552
- /**
553
- * Draw centerpin if requested
554
- */
555
- if (prop['chart.centerpin']) {
556
- this.DrawCenterpin();
557
- }
558
-
559
-
560
-
561
-
562
- /**
563
- * Draw ingraph labels
564
- */
565
- if (prop['chart.labels.ingraph']) {
566
- this.DrawInGraphLabels();
567
- }
568
-
569
-
570
-
571
-
572
- /**
573
- * Draw the center label if requested
574
- */
575
- if (!RG.isNull(prop['chart.labels.center'])) {
576
- this.drawCenterLabel(prop['chart.labels.center']);
577
- }
578
-
579
-
580
- /**
581
- * Setup the context menu if required
582
- */
583
- if (prop['chart.contextmenu']) {
584
- RG.ShowContext(this);
585
- }
586
-
587
-
588
-
589
- /**
590
- * If a border is pecified, draw it
591
- */
592
- if (prop['chart.border']) {
593
- co.beginPath();
594
- co.lineWidth = 5;
595
- co.strokeStyle = prop['chart.border.color'];
596
-
597
- co.arc(this.centerx,
598
- this.centery,
599
- this.radius - 2,
600
- 0,
601
- RG.TWOPI,
602
- 0);
603
-
604
- co.stroke();
605
- }
606
-
607
- /**
608
- * Draw the kay if desired
609
- */
610
- if (prop['chart.key'] && prop['chart.key'].length) {
611
- RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
612
- }
613
-
614
- RG.NoShadow(this);
615
-
616
-
617
- /**
618
- * This function enables resizing
619
- */
620
- if (prop['chart.resizable']) {
621
- RG.AllowResizing(this);
622
- }
623
-
624
-
625
- /**
626
- * This installs the event listeners
627
- */
628
- if (prop['chart.events'] == true) {
629
- RG.InstallEventListeners(this);
630
- }
631
-
632
-
633
- /**
634
- * Fire the onfirstdraw event
635
- */
636
- if (this.firstDraw) {
637
- RG.fireCustomEvent(this, 'onfirstdraw');
638
- this.firstDraw = false;
639
- this.firstDrawFunc();
640
- }
641
-
642
-
643
-
644
-
645
- /**
646
- * Fire the RGraph ondraw event
647
- */
648
- RG.FireCustomEvent(this, 'ondraw');
649
-
650
- return this;
651
- };
652
-
653
-
654
-
655
- /**
656
- * Used in chaining. Runs a function there and then - not waiting for
657
- * the events to fire (eg the onbeforedraw event)
658
- *
659
- * @param function func The function to execute
660
- */
661
- this.exec = function (func)
662
- {
663
- func(this);
664
-
665
- return this;
666
- };
667
-
668
-
669
-
670
-
671
- /**
672
- * Draws a single segment of the pie chart
673
- *
674
- * @param int degrees The number of degrees for this segment
675
- */
676
- this.drawSegment =
677
- this.DrawSegment = function (radians, color, last, index)
678
- {
679
- // IE7/8/ExCanvas fix (when there's only one segment the Pie chart doesn't display
680
- if (RGraph.ISOLD && radians == RG.TWOPI) {
681
- radians -= 0.0001;
682
- } else if (RGraph.ISOLD && radians == 0) {
683
- radians = 0.001;
684
- }
685
-
686
- var subTotal = this.subTotal;
687
- radians = radians * prop['chart.effect.roundrobin.multiplier'];
688
-
689
- co.beginPath();
690
-
691
- color ? co.fillStyle = color : null;
692
- co.strokeStyle = prop['chart.strokestyle'];
693
- co.lineWidth = 0;
694
-
695
- if (prop['chart.shadow']) {
696
- RG.setShadow(
697
- this,
698
- prop['chart.shadow.color'],
699
- prop['chart.shadow.offsetx'],
700
- prop['chart.shadow.offsety'],
701
- prop['chart.shadow.blur']
702
- );
703
- }
704
-
705
- /**
706
- * Exploded segments
707
- */
708
- if ( (typeof(prop['chart.exploded']) == 'object' && prop['chart.exploded'][index] > 0) || typeof(prop['chart.exploded']) == 'number') {
709
-
710
- var explosion = typeof(prop['chart.exploded']) == 'number' ? prop['chart.exploded'] : prop['chart.exploded'][index];
711
- var x = 0;
712
- var y = 0;
713
- var h = explosion;
714
- var t = subTotal + (radians / 2);
715
- var x = (Math.cos(t) * explosion);
716
- var y = (Math.sin(t) * explosion);
717
- var r = this.radius;
718
-
719
- co.moveTo(this.centerx + x, this.centery + y);
720
- } else {
721
- var x = 0;
722
- var y = 0;
723
- var r = this.radius;
724
- }
725
-
726
- /**
727
- * Calculate the angles
728
- */
729
- var startAngle = subTotal;
730
- var endAngle = ((subTotal + radians));
731
-
732
- co.arc(this.centerx + x,
733
- this.centery + y,
734
- r,
735
- startAngle,
736
- endAngle,
737
- 0);
738
-
739
- if (prop['chart.variant'] == 'donut') {
740
-
741
- co.arc(this.centerx + x,
742
- this.centery + y,
743
- typeof(prop['chart.variant.donut.width']) == 'number' ? r - prop['chart.variant.donut.width'] : r / 2,
744
- endAngle,
745
- startAngle,
746
- true);
747
- } else {
748
- co.lineTo(this.centerx + x, this.centery + y);
749
- }
750
-
751
- co.closePath();
752
-
753
-
754
- // Keep hold of the angles
755
- this.angles.push([subTotal, subTotal + radians, this.centerx + x, this.centery + y]);
756
-
757
-
758
-
759
- //co.stroke();
760
- co.fill();
761
-
762
- /**
763
- * Calculate the segment angle
764
- */
765
- this.subTotal += radians;
766
- };
767
-
768
-
769
-
770
-
771
- /**
772
- * Draws the graphs labels
773
- */
774
- this.drawLabels =
775
- this.DrawLabels = function ()
776
- {
777
- // New way of spacing labels out
778
- if (prop['chart.labels'].length && prop['chart.labels.sticks.list']) {
779
- return this.drawLabelsList();
780
- }
781
-
782
- var hAlignment = 'left',
783
- vAlignment = 'center',
784
- labels = prop['chart.labels'],
785
- context = co,
786
- font = prop['chart.text.font'],
787
- bold = prop['chart.labels.bold'],
788
- text_size = prop['chart.text.size'],
789
- cx = this.centerx,
790
- cy = this.centery,
791
- r = this.radius;
792
-
793
- /**
794
- * Turn the shadow off
795
- */
796
- RG.noShadow(this);
797
-
798
- co.fillStyle = 'black';
799
- co.beginPath();
800
-
801
- /**
802
- * Draw the labels
803
- */
804
- if (labels && labels.length) {
805
-
806
- for (i=0; i<this.angles.length; ++i) {
807
-
808
- var segment = this.angles[i];
809
-
810
- if (typeof labels[i] != 'string' && typeof labels[i] != 'number') {
811
- continue;
812
- }
813
-
814
- // Move to the centre
815
- co.moveTo(cx,cy);
816
-
817
- var a = segment[0] + ((segment[1] - segment[0]) / 2),
818
- angle = ((segment[1] - segment[0]) / 2) + segment[0];
819
-
820
- /**
821
- * Handle the additional "explosion" offset
822
- */
823
- if (typeof prop['chart.exploded'] === 'object' && prop['chart.exploded'][i] || typeof prop['chart.exploded'] == 'number') {
824
-
825
- var t = ((segment[1] - segment[0]) / 2),
826
- seperation = typeof(prop['chart.exploded']) == 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i];
827
-
828
- // Adjust the angles
829
- var explosion_offsetx = (Math.cos(angle) * seperation),
830
- explosion_offsety = (Math.sin(angle) * seperation);
831
- } else {
832
- var explosion_offsetx = 0,
833
- explosion_offsety = 0;
834
- }
835
-
836
- /**
837
- * Allow for the label sticks
838
- */
839
- if (prop['chart.labels.sticks']) {
840
- explosion_offsetx += (ma.cos(angle) * (typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length']) );
841
- explosion_offsety += (ma.sin(angle) * (typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length']) );
842
- }
843
-
844
- /**
845
- * Coords for the text
846
- */
847
- var x = cx + explosion_offsetx + ((r + 10)* Math.cos(a)) + (prop['chart.labels.sticks'] ? (a < RG.HALFPI || a > (RG.TWOPI + RG.HALFPI) ? 2 : -2) : 0),
848
- y = cy + explosion_offsety + (((r + 10) * Math.sin(a)));
849
-
850
-
851
-
852
-
853
- /**
854
- * If sticks are enabled use the endpoints that have been saved
855
- */
856
- if (this.coordsSticks && this.coordsSticks[i]) {
857
- var x = this.coordsSticks[i][4][0] + (x < cx ? -5 : 5),
858
- y = this.coordsSticks[i][4][1];
859
- }
860
-
861
-
862
- /**
863
- * Alignment
864
- */
865
- //vAlignment = y < cy ? 'center' : 'center';
866
- vAlignment = 'center';
867
- hAlignment = x < cx ? 'right' : 'left';
868
-
869
- co.fillStyle = prop['chart.text.color'];
870
- if ( typeof prop['chart.labels.colors'] === 'object' && prop['chart.labels.colors'] && prop['chart.labels.colors'][i]) {
871
- co.fillStyle = prop['chart.labels.colors'][i];
872
- }
873
-
874
-
875
- RG.text2(this, {
876
- font: font,
877
- size: text_size,
878
- x: x,
879
- y: y,
880
- text: labels[i],
881
- valign: vAlignment,
882
- halign: hAlignment,
883
- tag: 'labels',
884
- bold: bold,
885
- color: prop['chart.labels.sticks.usecolors'] ? prop['chart.colors'][i] : 'black'
886
- });
887
- }
888
-
889
- co.fill();
890
- }
891
- };
892
-
893
-
894
-
895
-
896
- //
897
- // A new way of spacing out labels
898
- //
899
- this.drawLabelsList = function ()
900
- {
901
- var segment = this.angles[i],
902
- labels = prop['chart.labels'],
903
- labels_right = [],
904
- labels_left = [],
905
- text_font = prop['chart.text.font'],
906
- text_size = prop['chart.text.size'],
907
- text_color = prop['chart.text.color'],
908
- left = [],
909
- right = [],
910
- centerx = this.centerx,
911
- centery = this.centery,
912
- radius = this.radius,
913
- offset = 50
914
-
915
-
916
-
917
-
918
-
919
-
920
-
921
-
922
- //
923
- // Draw the right hand side labels first
924
- //
925
- for (var i=0; i<this.angles.length; ++i) {
926
-
927
- var angle = this.angles[i][0] + ((this.angles[i][1] - this.angles[i][0]) / 2), // Midpoint
928
- endpoint_inner = RG.getRadiusEndPoint(centerx, centery, angle, radius + 5),
929
- endpoint_outer = RG.getRadiusEndPoint(centerx, centery, angle, radius + 10),
930
- explosion = [
931
- (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]),
932
- (ma.cos(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i])),
933
- (ma.sin(angle) * (typeof prop['chart.exploded'] === 'number' ? prop['chart.exploded'] : prop['chart.exploded'][i]))
934
- ]
935
-
936
-
937
- //
938
- // Work out the color
939
- //
940
- if ( typeof prop['chart.labels.sticks.colors'] === 'object' && prop['chart.labels.sticks.colors'] && prop['chart.labels.sticks.colors'][i] ) {
941
- var color = prop['chart.labels.sticks.colors'][i];
942
- } else if ( prop['chart.labels.sticks.usecolors'] && prop['chart.colors'][i] ) {
943
- var color = prop['chart.colors'][i];
944
- } else {
945
- var color = prop['chart.text.color'];
946
- }
947
-
948
-
949
-
950
-
951
- if (angle > (-1 * RG.HALFPI) && angle < RG.HALFPI) {
952
- labels_right.push([
953
- i,
954
- angle,
955
- labels[i] ? labels[i] : '',
956
- endpoint_inner,
957
- endpoint_outer,
958
- color,
959
- RG.arrayClone(explosion)
960
- ]);
961
- } else {
962
- labels_left.push([
963
- i,
964
- angle,
965
- labels[i] ? labels[i] : '',
966
- endpoint_inner,
967
- endpoint_outer,
968
- color,
969
- RG.arrayClone(explosion)
970
- ]);
971
- }
972
- }
973
-
974
-
975
-
976
-
977
- //
978
- // Draw the right hand side labels first
979
- //
980
-
981
-
982
- // Calculate how much space there is for each label
983
- var vspace_right = (ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / labels_right.length
984
-
985
- for (var i=0,y=(prop['chart.gutter.top'] + (vspace_right / 2)); i<labels_right.length; y+=vspace_right,i++) {
986
-
987
- if (labels_right[i][2]) {
988
-
989
- var x = this.centerx + this.radius + offset,
990
- idx = labels_right[i][0],
991
- explosionX = labels_right[i][6][0] ? labels_right[i][6][1] : 0,
992
- explosionY = labels_right[i][6][0] ? labels_right[i][6][2] : 0
993
-
994
- var ret = RG.text2(this, {
995
- font: text_font,
996
- size: text_size,
997
- x: x + explosionX,
998
- y: y + explosionY,
999
- text: labels_right[i][2],
1000
- valign: 'center',
1001
- halign: 'left',
1002
- tag: 'labels',
1003
- color: labels_right[i][5]
1004
- });
1005
-
1006
- if (ret && ret.node) {
1007
- ret.node.__index__ = labels_right[i][0];
1008
- }
1009
-
1010
-
1011
- pa2(co, 'lc round lw % b m % % l % % l % % l % % s %',
1012
-
1013
- prop['chart.labels.sticks.linewidth'],
1014
-
1015
- labels_right[i][3][0] + explosionX,
1016
- labels_right[i][3][1] + explosionY,
1017
-
1018
- labels_right[i][4][0] + explosionX,
1019
- labels_right[i][4][1] + explosionY,
1020
-
1021
- this.centerx + this.radius + 25 + explosionX,
1022
- ma.round(labels_right[i][4][1] + explosionY),
1023
-
1024
- ret.x - 5 ,
1025
- ret.y + (ret.height / 2),
1026
-
1027
- labels_right[i][5]
1028
- );
1029
- }
1030
- }
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
-
1040
- //
1041
- // Draw the left hand side labels
1042
- //
1043
-
1044
-
1045
-
1046
-
1047
-
1048
- // Calculate how much space there is for each label
1049
- var vspace_left = (ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / labels_left.length
1050
-
1051
- for (var i=(labels_left.length - 1),y=(prop['chart.gutter.top'] + (vspace_left / 2)); i>=0; y+=vspace_left,i--) {
1052
-
1053
- if (labels_left[i][2]) {
1054
-
1055
- var x = this.centerx - this.radius - offset,
1056
- idx = labels_left[i][0],
1057
- explosionX = labels_left[i][6][0] ? labels_left[i][6][1] : 0,
1058
- explosionY = labels_left[i][6][0] ? labels_left[i][6][2] : 0
1059
-
1060
- var ret = RG.text2(this, {
1061
- font: text_font,
1062
- size: text_size,
1063
- x: x + explosionX,
1064
- y: y + explosionY,
1065
- text: labels_left[i][2],
1066
- valign: 'center',
1067
- halign: 'right',
1068
- tag: 'labels',
1069
- color: labels_left[i][5]
1070
- });
1071
-
1072
- if (ret && ret.node) {
1073
- ret.node.__index__ = labels_left[i][0];
1074
- }
1075
-
1076
- pa2(co,
1077
- 'lw % b m % % l % % l % % l % % s %',
1078
-
1079
- prop['chart.labels.sticks.linewidth'],
1080
-
1081
- labels_left[i][3][0] + explosionX,
1082
- labels_left[i][3][1] + explosionY,
1083
-
1084
- labels_left[i][4][0] + explosionX,
1085
- labels_left[i][4][1] + explosionY,
1086
-
1087
- this.centerx - this.radius - 25 + explosionX,
1088
- ma.round(labels_left[i][4][1] + explosionY),
1089
-
1090
- ret.x + 5 + ret.width,
1091
- ret.y + (ret.height / 2),
1092
-
1093
- labels_left[i][5]
1094
- );
1095
- }
1096
- }
1097
- };
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
-
1115
-
1116
-
1117
- /**
1118
- * This function draws the pie chart sticks (for the labels)
1119
- */
1120
- this.drawSticks =
1121
- this.DrawSticks = function ()
1122
- {
1123
- var offset = prop['chart.linewidth'] / 2,
1124
- exploded = prop['chart.exploded'],
1125
- sticks = prop['chart.labels.sticks'],
1126
- colors = prop['chart.colors'],
1127
- cx = this.centerx,
1128
- cy = this.centery,
1129
- radius = this.radius,
1130
- points = [],
1131
- linewidth = prop['chart.labels.sticks.linewidth']
1132
-
1133
- for (var i=0,len=this.angles.length; i<len; ++i) {
1134
-
1135
- var segment = this.angles[i];
1136
-
1137
- // This allows the chart.labels.sticks to be an array as well as a boolean
1138
- if (typeof sticks === 'object' && !sticks[i]) {
1139
- continue;
1140
- }
1141
-
1142
- var radians = segment[1] - segment[0];
1143
-
1144
- co.beginPath();
1145
- co.strokeStyle = typeof prop['chart.labels.sticks.colors'] === 'string' ? prop['chart.labels.sticks.colors'] : (!RG.isNull(prop['chart.labels.sticks.colors']) ? prop['chart.labels.sticks.colors'][i] : 'gray');
1146
- co.lineWidth = linewidth;
1147
-
1148
- if (typeof prop['chart.labels.sticks.color'] === 'string') {
1149
- co.strokeStyle = prop['chart.labels.sticks.color'];
1150
- }
1151
-
1152
- //
1153
- // Allow for labelsSticksUseColors
1154
- //
1155
- if (prop['chart.labels.sticks.usecolors']) {
1156
- co.strokeStyle = prop['chart.colors'][i];
1157
- }
1158
-
1159
- var midpoint = (segment[0] + (radians / 2));
1160
-
1161
- if (typeof exploded === 'object' && exploded[i]) {
1162
- var extra = exploded[i];
1163
- } else if (typeof exploded === 'number') {
1164
- var extra = exploded;
1165
- } else {
1166
- var extra = 0;
1167
- }
1168
-
1169
- /**
1170
- * Determine the stick length
1171
- */
1172
- var stickLength = typeof prop['chart.labels.sticks.length'] === 'object' ? prop['chart.labels.sticks.length'][i] : prop['chart.labels.sticks.length'];
1173
-
1174
-
1175
- points[0] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + extra + offset);
1176
- points[1] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra - 5);
1177
-
1178
- points[2] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra);
1179
-
1180
- points[3] = RG.getRadiusEndPoint(cx, cy, midpoint, radius + stickLength + extra);
1181
- points[3][0] += (points[3][0] > cx ? 5 : -5);
1182
-
1183
- points[4] = [
1184
- points[2][0] + (points[2][0] > cx ? 5 + prop['chart.labels.sticks.hlength'] : -5 - prop['chart.labels.sticks.hlength']),
1185
- points[2][1]
1186
- ];
1187
-
1188
-
1189
- co.moveTo(points[0][0], points[0][1]);
1190
- co.quadraticCurveTo(points[2][0], points[2][1], points[4][0], points[4][1]);
1191
-
1192
- co.stroke();
1193
-
1194
- /**
1195
- * Save the stick end coords
1196
- */
1197
- this.coordsSticks[i] = [points[0],points[1], points[2], points[3], points[4]];
1198
- }
1199
- };
1200
-
1201
-
1202
-
1203
-
1204
- /**
1205
- * The (now Pie chart specific) getSegment function
1206
- *
1207
- * @param object e The event object
1208
- */
1209
- this.getShape =
1210
- this.getSegment = function (e)
1211
- {
1212
- RG.FixEventObject(e);
1213
-
1214
- // The optional arg provides a way of allowing some accuracy (pixels)
1215
- var accuracy = arguments[1] ? arguments[1] : 0;
1216
-
1217
- var canvas = ca;
1218
- var context = co;
1219
- var mouseCoords = RG.getMouseXY(e);
1220
- var mouseX = mouseCoords[0];
1221
- var mouseY = mouseCoords[1];
1222
- var r = this.radius;
1223
- var angles = this.angles;
1224
- var ret = [];
1225
-
1226
- for (var i=0,len=angles.length; i<len; ++i) {
1227
-
1228
- // DRAW THE SEGMENT AGAIN SO IT CAN BE TESTED //////////////////////////
1229
- co.beginPath();
1230
- co.strokeStyle = 'rgba(0,0,0,0)';
1231
- co.arc(angles[i][2], angles[i][3], this.radius, angles[i][0], angles[i][1], false);
1232
-
1233
- if (this.type == 'pie' && prop['chart.variant'] == 'donut') {
1234
- co.arc(angles[i][2], angles[i][3], (typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : this.radius / 2), angles[i][1], angles[i][0], true);
1235
- } else {
1236
- co.lineTo(angles[i][2], angles[i][3]);
1237
- }
1238
- co.closePath();
1239
-
1240
- if (!co.isPointInPath(mouseX, mouseY)) {
1241
- continue;
1242
- }
1243
-
1244
- ////////////////////////////////////////////////////////////////////////
1245
-
1246
- ret[0] = angles[i][2];
1247
- ret[1] = angles[i][3];
1248
- ret[2] = this.radius;
1249
- ret[3] = angles[i][0] - RG.TWOPI;
1250
- ret[4] = angles[i][1];
1251
- ret[5] = i;
1252
-
1253
-
1254
-
1255
- if (ret[3] < 0) ret[3] += RG.TWOPI;
1256
- if (ret[4] > RG.TWOPI) ret[4] -= RG.TWOPI;
1257
-
1258
- /**
1259
- * Add the tooltip to the returned shape
1260
- */
1261
- var tooltip = RG.parseTooltipText ? RG.parseTooltipText(prop['chart.tooltips'], ret[5]) : null;
1262
-
1263
- /**
1264
- * Now return textual keys as well as numerics
1265
- */
1266
- ret['object'] = this;
1267
- ret['x'] = ret[0];
1268
- ret['y'] = ret[1];
1269
- ret['radius'] = ret[2];
1270
- ret['angle.start'] = ret[3];
1271
- ret['angle.end'] = ret[4];
1272
- ret['index'] = ret[5];
1273
- ret['tooltip'] = tooltip;
1274
-
1275
- return ret;
1276
- }
1277
-
1278
- return null;
1279
- };
1280
-
1281
-
1282
-
1283
-
1284
- this.drawBorders =
1285
- this.DrawBorders = function ()
1286
- {
1287
- if (prop['chart.linewidth'] > 0) {
1288
-
1289
- co.lineWidth = prop['chart.linewidth'];
1290
- co.strokeStyle = prop['chart.strokestyle'];
1291
-
1292
- var r = this.radius;
1293
-
1294
- for (var i=0,len=this.angles.length; i<len; ++i) {
1295
-
1296
- var segment = this.angles[i];
1297
-
1298
- co.beginPath();
1299
- co.arc(segment[2],
1300
- segment[3],
1301
- r,
1302
- (segment[0]),
1303
- (segment[0] + 0.001),
1304
- 0);
1305
- co.arc(segment[2],
1306
- segment[3],
1307
- prop['chart.variant'] == 'donut' ? (typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : r / 2): r,
1308
- segment[0],
1309
- segment[0] + 0.0001,
1310
- 0);
1311
- co.closePath();
1312
- co.stroke();
1313
- }
1314
- }
1315
- };
1316
-
1317
-
1318
-
1319
-
1320
- /**
1321
- * Returns the radius of the pie chart
1322
- *
1323
- * [06-02-2012] Maintained for compatibility ONLY.
1324
- */
1325
- this.getRadius = function ()
1326
- {
1327
- this.graph = {width: ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'], height: ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']}
1328
-
1329
- if (typeof(prop['chart.radius']) == 'number') {
1330
- this.radius = prop['chart.radius'];
1331
- } else {
1332
- this.radius = Math.min(this.graph.width, this.graph.height) / 2;
1333
- }
1334
-
1335
- return this.radius;
1336
- };
1337
-
1338
-
1339
-
1340
-
1341
- /**
1342
- * A programmatic explode function
1343
- *
1344
- * @param object obj The chart object
1345
- * @param number index The zero-indexed number of the segment
1346
- * @param number size The size (in pixels) of the explosion
1347
- */
1348
- this.explodeSegment =
1349
- this.Explode = function (index, size)
1350
- {
1351
- if (typeof this.exploding === 'number' && this.exploding === index) {
1352
- return;
1353
- }
1354
-
1355
- //this.Set('chart.exploded', []);
1356
- if (!prop['chart.exploded']) {
1357
- prop['chart.exploded'] = [];
1358
- }
1359
-
1360
- // If chart.exploded is a number - convert it to an array
1361
- if (typeof(prop['chart.exploded']) == 'number') {
1362
-
1363
- var original_explode = prop['chart.exploded'];
1364
- var exploded = prop['chart.exploded'];
1365
-
1366
- prop['chart.exploded'] = [];
1367
-
1368
- for (var i=0,len=this.data.length; i<len; ++i) {
1369
- prop['chart.exploded'][i] = exploded;
1370
- }
1371
- }
1372
-
1373
- prop['chart.exploded'][index] = typeof(original_explode) == 'number' ? original_explode : 0;
1374
-
1375
- this.exploding = index;
1376
- var delay = RG.ISIE && !RG.ISIE10 ? 25 : 16.666;
1377
-
1378
- for (var o=0; o<size; ++o) {
1379
-
1380
- setTimeout(
1381
- function ()
1382
- {
1383
- prop['chart.exploded'][index] += 1;
1384
- RG.Clear(ca);
1385
- RG.RedrawCanvas(ca);
1386
- }, o * delay);
1387
- }
1388
-
1389
- var obj = this;
1390
- setTimeout(function ()
1391
- {
1392
- obj.exploding = null;
1393
- }, size * delay);
1394
- };
1395
-
1396
-
1397
-
1398
-
1399
- /**
1400
- * This function highlights a segment
1401
- *
1402
- * @param array segment The segment information that is returned by the pie.getSegment(e) function
1403
- */
1404
- this.highlight_segment = function (segment)
1405
- {
1406
- co.beginPath();
1407
- co.strokeStyle = prop['chart.highlight.style.twod.stroke'];
1408
- co.fillStyle = prop['chart.highlight.style.twod.fill'];
1409
- co.moveTo(segment[0], segment[1]);
1410
- co.arc(segment[0], segment[1], segment[2], this.angles[segment[5]][0], this.angles[segment[5]][1], 0);
1411
- co.lineTo(segment[0], segment[1]);
1412
- co.closePath();
1413
-
1414
- co.stroke();
1415
- co.fill();
1416
- };
1417
-
1418
-
1419
-
1420
-
1421
- /**
1422
- * Each object type has its own Highlight() function which highlights
1423
- * the appropriate shape
1424
- *
1425
- * @param object shape The shape to highlight
1426
- */
1427
- this.highlight =
1428
- this.Highlight = function (shape)
1429
- {
1430
- if (prop['chart.tooltips.highlight']) {
1431
-
1432
- if (typeof prop['chart.highlight.style'] === 'function') {
1433
- (prop['chart.highlight.style'])(shape);
1434
-
1435
- /**
1436
- * 3D style of highlighting
1437
- */
1438
- } else if (prop['chart.highlight.style'] == '3d') {
1439
-
1440
- co.lineWidth = 1;
1441
-
1442
- // This is the extent of the 2D effect. Bigger values will give the appearance of a larger "protusion"
1443
- var extent = 2;
1444
-
1445
- // Draw a white-out where the segment is
1446
- co.beginPath();
1447
- RG.NoShadow(this);
1448
- co.fillStyle = 'rgba(0,0,0,0)';
1449
- co.arc(shape['x'], shape['y'], shape['radius'], shape['angle.start'], shape['angle.end'], false);
1450
- if (prop['chart.variant'] == 'donut') {
1451
- co.arc(shape['x'], shape['y'], shape['radius'] / 5, shape['angle.end'], shape['angle.start'], true);
1452
- } else {
1453
- co.lineTo(shape['x'], shape['y']);
1454
- }
1455
- co.closePath();
1456
- co.fill();
1457
-
1458
- // Draw the new segment
1459
- co.beginPath();
1460
-
1461
- co.shadowColor = '#666';
1462
- co.shadowBlur = 3;
1463
- co.shadowOffsetX = 3;
1464
- co.shadowOffsetY = 3;
1465
-
1466
- co.fillStyle = prop['chart.colors'][shape['index']];
1467
- co.strokeStyle = prop['chart.strokestyle'];
1468
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'], shape['angle.start'], shape['angle.end'], false);
1469
- if (prop['chart.variant'] == 'donut') {
1470
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'] / 2, shape['angle.end'], shape['angle.start'], true)
1471
- } else {
1472
- co.lineTo(shape['x'] - extent, shape['y'] - extent);
1473
- }
1474
- co.closePath();
1475
-
1476
- co.stroke();
1477
- co.fill();
1478
-
1479
- // Turn off the shadow
1480
- RG.NoShadow(this);
1481
-
1482
- /**
1483
- * If a border is defined, redraw that
1484
- */
1485
- if (prop['chart.border']) {
1486
- co.beginPath();
1487
- co.strokeStyle = prop['chart.border.color'];
1488
- co.lineWidth = 5;
1489
- co.arc(shape['x'] - extent, shape['y'] - extent, shape['radius'] - 2, shape['angle.start'], shape['angle.end'], false);
1490
- co.stroke();
1491
- }
1492
-
1493
-
1494
-
1495
-
1496
- // Outline style of highlighting
1497
- } else if (prop['chart.highlight.style'] === 'outline') {
1498
-
1499
- var tooltip = RG.Registry.get('chart.tooltip'),
1500
- index = tooltip.__index__,
1501
- coords = this.angles[index],
1502
- color = this.get('colors')[index]
1503
- width = this.radius / 12.5;
1504
-
1505
- // Allow custom setting of outline
1506
- if (typeof prop['chart.highlight.style.outline.width'] === 'number') {
1507
- width = prop['chart.highlight.style.outline.width'];
1508
- }
1509
-
1510
-
1511
-
1512
- RGraph.path2(
1513
- co,
1514
- 'ga 0.25 b a % % % % % false a % % % % % true c f % ga 1',
1515
- coords[2],
1516
- coords[3],
1517
- this.radius + 2 + width,
1518
- coords[0],
1519
- coords[1],
1520
-
1521
- coords[2],
1522
- coords[3],
1523
- this.radius + 2,
1524
- coords[1],
1525
- coords[0],
1526
- color
1527
- );
1528
-
1529
-
1530
-
1531
-
1532
-
1533
-
1534
- // Default 2D style of highlighting
1535
- } else {
1536
-
1537
- co.beginPath();
1538
-
1539
- co.strokeStyle = prop['chart.highlight.style.twod.stroke'];
1540
- co.fillStyle = prop['chart.highlight.style.twod.fill'];
1541
-
1542
- if (prop['chart.variant'].indexOf('donut') > -1) {
1543
- co.arc(shape['x'], shape['y'], shape['radius'], shape['angle.start'], shape['angle.end'], false);
1544
- co.arc(shape['x'], shape['y'], typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : shape['radius'] / 2, shape['angle.end'], shape['angle.start'], true);
1545
- } else {
1546
- co.arc(shape['x'], shape['y'], shape['radius'] + 1, shape['angle.start'], shape['angle.end'], false);
1547
- co.lineTo(shape['x'], shape['y']);
1548
- }
1549
- co.closePath();
1550
-
1551
- co.stroke();
1552
- co.fill();
1553
- }
1554
- }
1555
- };
1556
-
1557
-
1558
-
1559
-
1560
- /**
1561
- * The getObjectByXY() worker method. The Pie chart is able to use the
1562
- * getShape() method - so it does.
1563
- */
1564
- this.getObjectByXY = function (e)
1565
- {
1566
- if (this.getShape(e)) {
1567
- return this;
1568
- }
1569
- };
1570
-
1571
-
1572
-
1573
-
1574
- /**
1575
- * Draws the centerpin if requested
1576
- */
1577
- this.drawCenterpin =
1578
- this.DrawCenterpin = function ()
1579
- {
1580
- if (typeof(prop['chart.centerpin']) == 'number' && prop['chart.centerpin'] > 0) {
1581
-
1582
- var cx = this.centerx;
1583
- var cy = this.centery;
1584
-
1585
- co.beginPath();
1586
- co.strokeStyle = prop['chart.centerpin.stroke'] ? prop['chart.centerpin.stroke'] : prop['chart.strokestyle'];
1587
- co.fillStyle = prop['chart.centerpin.fill'] ? prop['chart.centerpin.fill'] : prop['chart.strokestyle'];
1588
- co.moveTo(cx, cy);
1589
- co.arc(cx, cy, prop['chart.centerpin'], 0, RG.TWOPI, false);
1590
- co.stroke();
1591
- co.fill();
1592
- }
1593
- };
1594
-
1595
-
1596
-
1597
-
1598
- /**
1599
- * This function positions a tooltip when it is displayed
1600
- *
1601
- * @param obj object The chart object
1602
- * @param int x The X coordinate specified for the tooltip
1603
- * @param int y The Y coordinate specified for the tooltip
1604
- * @param objec tooltip The tooltips DIV element
1605
- *
1606
- this.positionTooltip = function (obj, x, y, tooltip, idx)
1607
- {
1608
- var coordX = obj.angles[idx][2];
1609
- var coordY = obj.angles[idx][3];
1610
- var mouseXY = RG.getMouseXY(window.event);
1611
- var angleStart = obj.angles[idx][0];
1612
- var angleEnd = obj.angles[idx][1];
1613
- var angleCenter = ((angleEnd - angleStart) / 2) + angleStart;
1614
- var canvasXY = RGraph.getCanvasXY(obj.canvas);
1615
- var gutterLeft = prop['chart.gutter.left'];
1616
- var gutterTop = prop['chart.gutter.top'];
1617
- var width = tooltip.offsetWidth;
1618
- var height = tooltip.offsetHeight;
1619
- var x = canvasXY[0] + this.angles[idx][2] + (Math.cos(angleCenter) * (prop['chart.variant'] == 'donut' && typeof(prop['chart.variant.donut.width']) == 'number' ? ((this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2)) : (this.radius * 0.5)));
1620
- var y = canvasXY[1] + this.angles[idx][3] + (Math.sin(angleCenter) * (prop['chart.variant'] == 'donut' && typeof(prop['chart.variant.donut.width']) == 'number' ? ((this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2)) : (this.radius * 0.5)));
1621
-
1622
-
1623
- // By default any overflow is hidden
1624
- tooltip.style.overflow = '';
1625
-
1626
- // Set the top position
1627
- tooltip.style.left = 0;
1628
- tooltip.style.top = window.event.pageY - height - 5 + 'px';
1629
-
1630
-
1631
- // Reposition the tooltip if at the edges:
1632
-
1633
- // LEFT edge
1634
- if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
1635
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
1636
-
1637
- // RIGHT edge
1638
- } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
1639
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
1640
-
1641
- // Default positioning - CENTERED
1642
- } else {
1643
- tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
1644
- }
1645
- };*/
1646
-
1647
-
1648
-
1649
-
1650
- /**
1651
- * This draws Ingraph labels
1652
- */
1653
- this.drawInGraphLabels =
1654
- this.DrawInGraphLabels = function ()
1655
- {
1656
- var context = co;
1657
- var cx = this.centerx;
1658
- var cy = this.centery;
1659
- var radius = prop['chart.labels.ingraph.radius'];
1660
-
1661
- //
1662
- // Is the radius less than 2? If so then it's a factor and not n exact point
1663
- //
1664
- if (radius <= 2 && radius > 0) {
1665
- radiusFactor = radius;
1666
- } else {
1667
- radiusFactor = 0.5;
1668
- }
1669
-
1670
- if (prop['chart.variant'] == 'donut') {
1671
- var r = this.radius * (0.5 + (radiusFactor * 0.5));
1672
-
1673
- if (typeof(prop['chart.variant.donut.width']) == 'number') {
1674
- var r = (this.radius - prop['chart.variant.donut.width']) + (prop['chart.variant.donut.width'] / 2);
1675
- }
1676
- } else {
1677
- var r = this.radius * radiusFactor;
1678
- }
1679
-
1680
- if (radius > 2) {
1681
- r = radius;
1682
- }
1683
-
1684
- for (var i=0,len=this.angles.length; i<len; ++i) {
1685
-
1686
- // This handles any explosion that the segment may have
1687
- if (typeof(prop['chart.exploded']) == 'object' && typeof(prop['chart.exploded'][i]) == 'number') {
1688
- var explosion = prop['chart.exploded'][i];
1689
- } else if (typeof(prop['chart.exploded']) == 'number') {
1690
- var explosion = parseInt(prop['chart.exploded']);
1691
- } else {
1692
- var explosion = 0;
1693
- }
1694
-
1695
- var angleStart = this.angles[i][0];
1696
- var angleEnd = this.angles[i][1];
1697
- var angleCenter = ((angleEnd - angleStart) / 2) + angleStart;
1698
- var coords = RG.getRadiusEndPoint(
1699
- this.centerx,
1700
- this.centery,
1701
- angleCenter,
1702
- r + (explosion ? explosion : 0)
1703
- );
1704
-
1705
- var x = coords[0];
1706
- var y = coords[1];
1707
-
1708
- var text = prop['chart.labels.ingraph.specific'] && typeof(prop['chart.labels.ingraph.specific'][i]) == 'string' ? prop['chart.labels.ingraph.specific'][i] : RG.number_format(this, this.data[i], prop['chart.labels.ingraph.units.pre'] , prop['chart.labels.ingraph.units.post']);
1709
-
1710
- if (text) {
1711
- co.beginPath();
1712
-
1713
- var font = typeof prop['chart.labels.ingraph.font'] === 'string' ? prop['chart.labels.ingraph.font'] : prop['chart.text.font'];
1714
- var size = typeof prop['chart.labels.ingraph.size'] === 'number' ? prop['chart.labels.ingraph.size'] : prop['chart.text.size'] + 2;
1715
-
1716
- //
1717
- // Set the colors
1718
- //
1719
- co.fillStyle = prop['chart.labels.ingraph.color'] ? prop['chart.labels.ingraph.color'] : 'black';
1720
-
1721
- RG.Text2(this, {
1722
- 'font':font,
1723
- 'size':size,
1724
- 'x':x,
1725
- 'y':y,
1726
- 'text':text,
1727
- 'valign':'center',
1728
- 'halign':'center',
1729
- 'bounding': prop['chart.labels.ingraph.bounding'],
1730
- 'bounding.fill': prop['chart.labels.ingraph.bounding.fill'],
1731
- 'tag':'labels.ingraph'
1732
- });
1733
- co.stroke();
1734
- }
1735
- }
1736
- };
1737
-
1738
-
1739
-
1740
-
1741
- //
1742
- // Draws the center label if required
1743
- //
1744
- this.drawCenterLabel = function (label)
1745
- {
1746
- var font = prop['chart.labels.center.font'],
1747
- size = prop['chart.labels.center.size'],
1748
- color = prop['chart.labels.center.color'],
1749
- unitsPre = prop['chart.labels.center.units.pre'],
1750
- unitsPost = prop['chart.labels.center.units.post'],
1751
- bold = prop['chart.labels.center.bold'],
1752
- italic = prop['chart.labels.center.italic'];
1753
-
1754
-
1755
- RG.text2(this, {
1756
- color: color,
1757
- bold: bold,
1758
- italic: italic,
1759
- font: font,
1760
- size: size,
1761
- x: this.centerx,
1762
- y: this.centery,
1763
- halign: 'center',
1764
- valign: 'center',
1765
- text: RG.numberFormat(this, label,unitsPre, unitsPost)
1766
- });
1767
- }
1768
-
1769
-
1770
-
1771
-
1772
- /**
1773
- * This returns the angle for a value based around the maximum number
1774
- *
1775
- * @param number value The value to get the angle for
1776
- */
1777
- this.getAngle = function (value)
1778
- {
1779
- if (value > this.total) {
1780
- return null;
1781
- }
1782
-
1783
- var angle = (value / this.total) * RG.TWOPI;
1784
-
1785
- // Handle the origin (it can br -HALFPI or 0)
1786
- angle += prop['chart.origin'];
1787
-
1788
- return angle;
1789
- };
1790
-
1791
-
1792
-
1793
-
1794
- /**
1795
- * This allows for easy specification of gradients
1796
- */
1797
- this.parseColors = function ()
1798
- {
1799
- // Save the original colors so that they can be restored when the canvas is reset
1800
- if (this.original_colors.length === 0) {
1801
- this.original_colors['chart.colors'] = RG.arrayClone(prop['chart.colors']);
1802
- this.original_colors['chart.key.colors'] = RG.arrayClone(prop['chart.key.colors']);
1803
- this.original_colors['chart.strokestyle'] = RG.arrayClone(prop['chart.strokestyle']);
1804
- this.original_colors['chart.highlight.stroke'] = RG.arrayClone(prop['chart.highlight.stroke']);
1805
- this.original_colors['chart.highlight.style.twod.fill'] = RG.arrayClone(prop['chart.highlight.style.twod.fill']);
1806
- this.original_colors['chart.highlight.style.twod.stroke'] = RG.arrayClone(prop['chart.highlight.style.twod.stroke']);
1807
- this.original_colors['chart.ingraph.bounding.fill'] = RG.arrayClone(prop['chart.ingraph.bounding.fill']);
1808
- this.original_colors['chart.ingraph.color'] = RG.arrayClone(prop['chart.ingraph.color']);
1809
- }
1810
-
1811
- for (var i=0; i<prop['chart.colors'].length; ++i) {
1812
- prop['chart.colors'][i] = this.parseSingleColorForGradient(prop['chart.colors'][i]);
1813
- }
1814
-
1815
- var keyColors = prop['chart.key.colors'];
1816
- if (keyColors) {
1817
- for (var i=0; i<keyColors.length; ++i) {
1818
- keyColors[i] = this.parseSingleColorForGradient(keyColors[i]);
1819
- }
1820
- }
1821
-
1822
- prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
1823
- prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1824
- prop['chart.highlight.style.twod.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.style.twod.fill']);
1825
- prop['chart.highlight.style.twod.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.style.twod.stroke']);
1826
- prop['chart.labels.ingraph.bounding.fill'] = this.parseSingleColorForGradient(prop['chart.labels.ingraph.bounding.fill']);
1827
- prop['chart.labels.ingraph.color'] = this.parseSingleColorForGradient(prop['chart.labels.ingraph.color']);
1828
- };
1829
-
1830
-
1831
-
1832
-
1833
- /**
1834
- * Use this function to reset the object to the post-constructor state. Eg reset colors if
1835
- * need be etc
1836
- */
1837
- this.reset = function ()
1838
- {
1839
- };
1840
-
1841
-
1842
-
1843
-
1844
- /**
1845
- * This parses a single color value
1846
- */
1847
- this.parseSingleColorForGradient = function (color)
1848
- {
1849
-
1850
- if (!color || typeof(color) != 'string') {
1851
- return color;
1852
- }
1853
-
1854
- if (color.match(/^gradient\((.*)\)$/i)) {
1855
-
1856
- var parts = RegExp.$1.split(':');
1857
-
1858
- // If the chart is a donut - the first width should half the total radius
1859
- if (prop['chart.variant'] == 'donut') {
1860
- var radius_start = typeof(prop['chart.variant.donut.width']) == 'number' ? this.radius - prop['chart.variant.donut.width'] : this.radius / 2;
1861
- } else {
1862
- var radius_start = 0;
1863
- }
1864
-
1865
- // Create the gradient
1866
- var grad = co.createRadialGradient(this.centerx, this.centery, radius_start, this.centerx, this.centery, Math.min(ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'], ca.height - prop['chart.gutter.top'] - prop['chart.gutter.bottom']) / 2);
1867
-
1868
-
1869
- var diff = 1 / (parts.length - 1);
1870
-
1871
- grad.addColorStop(0, RG.trim(parts[0]));
1872
-
1873
- for (var j=1; j<parts.length; ++j) {
1874
- grad.addColorStop(j * diff, RG.trim(parts[j]));
1875
- }
1876
- }
1877
-
1878
- return grad ? grad : color;
1879
- };
1880
-
1881
-
1882
-
1883
-
1884
- /**
1885
- * This function handles highlighting an entire data-series for the interactive
1886
- * key
1887
- *
1888
- * @param int index The index of the data series to be highlighted
1889
- */
1890
- this.interactiveKeyHighlight = function (index)
1891
- {
1892
- if (this.angles && this.angles[index]) {
1893
-
1894
- var segment = this.angles[index];
1895
- var x = segment[2];
1896
- var y = segment[3];
1897
- var start = segment[0];
1898
- var end = segment[1];
1899
-
1900
- co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
1901
- co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1902
- co.lineWidth = 2;
1903
- co.lineJoin = 'bevel';
1904
-
1905
- co.beginPath();
1906
- co.moveTo(x, y);
1907
- co.arc(x, y, this.radius, start, end, false);
1908
- co.closePath();
1909
- co.fill();
1910
- co.stroke();
1911
- }
1912
- };
1913
-
1914
-
1915
-
1916
-
1917
- /**
1918
- * Using a function to add events makes it easier to facilitate method chaining
1919
- *
1920
- * @param string type The type of even to add
1921
- * @param function func
1922
- */
1923
- this.on = function (type, func)
1924
- {
1925
- if (type.substr(0,2) !== 'on') {
1926
- type = 'on' + type;
1927
- }
1928
-
1929
- if (typeof this[type] !== 'function') {
1930
- this[type] = func;
1931
- } else {
1932
- RG.addCustomEventListener(this, type, func);
1933
- }
1934
-
1935
- return this;
1936
- };
1937
-
1938
-
1939
-
1940
-
1941
- /**
1942
- * This function runs once only
1943
- * (put at the end of the file (before any effects))
1944
- */
1945
- this.firstDrawFunc = function ()
1946
- {
1947
- };
1948
-
1949
-
1950
-
1951
-
1952
- //
1953
- // Draw a 3D Pie/Donut chart
1954
- //
1955
- this.draw3d = function ()
1956
- {
1957
- var scaleX = 1.5,
1958
- depth = prop['chart.variant.threed.depth'],
1959
- prop_shadow = prop['chart.shadow'],
1960
- prop_labels = prop['chart.labels'],
1961
- prop_labelsSticks = prop['chart.labels.sticks']
1962
-
1963
- this.set({
1964
- labels: [],
1965
- labelsSticks: false,
1966
- strokestyle: 'rgba(0,0,0,0)'
1967
- });
1968
-
1969
- //
1970
- // Change the variant so that the draw function doesn't keep
1971
- // coming in here
1972
- //
1973
- this.set({
1974
- variant: this.get('variant').replace(/3d/, '')
1975
- });
1976
-
1977
- this.context.setTransform(scaleX, 0, 0, 1, (ca.width * (scaleX) - ca.width) * -0.5, 0);
1978
-
1979
- for (var i=depth; i>0; i-=1) {
1980
-
1981
- this.set({
1982
- centeryAdjust: i
1983
- });
1984
-
1985
- if (i === parseInt(depth / 2) ) {
1986
- this.set({
1987
- labels: prop_labels,
1988
- labelsSticks: prop_labelsSticks
1989
- });
1990
- }
1991
-
1992
- if (i === 0) {
1993
- this.set({
1994
- shadow: prop_shadow
1995
- });
1996
- }
1997
-
1998
- this.draw();
1999
-
2000
- // Turn off the shadow after the bottom pie/donut has
2001
- // been drawn
2002
- this.set('shadow', false);
2003
-
2004
- //
2005
- // If on the middle pie/donut turn the labels and sticks off
2006
- //
2007
- if (i <= parseInt(depth / 2) ) {
2008
- this.set({
2009
- labels: [],
2010
- labelsSticks: false
2011
- });
2012
- }
2013
-
2014
- //
2015
- // Make what we're drawng darker by going over
2016
- // it in a semi-transparent dark color
2017
- //
2018
- if (i > 1) {
2019
- if (prop['chart.variant'].indexOf('donut') !== -1) {
2020
-
2021
- for (var j=0; j<this.angles.length; ++j) {
2022
- pa2(co,[
2023
- 'b',
2024
- 'a', this.angles[j][2], this.angles[j][3], this.radius + 1, this.angles[j][0], this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'], false,
2025
- 'a', this.angles[j][2], this.angles[j][3], this.radius / 2, this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'], this.angles[j][0], true,
2026
- 'f', 'rgba(0,0,0,0.15)'
2027
- ]);
2028
- }
2029
-
2030
- // Draw the pie chart darkened segments
2031
- } else {
2032
-
2033
- for (var j=0; j<this.angles.length; ++j) {
2034
-
2035
- pa2(co,[
2036
- 'b',
2037
- 'm', this.angles[j][2], this.angles[j][3],
2038
- 'a', this.angles[j][2],
2039
- this.angles[j][3],
2040
- this.radius + 1,
2041
- this.angles[j][0],
2042
- this.angles[j][1] * prop['chart.effect.roundrobin.multiplier'],
2043
- false,
2044
- 'c',
2045
- 'f', 'rgba(0,0,0,0.15)'
2046
- ]);
2047
- }
2048
- }
2049
- }
2050
- }
2051
-
2052
- //
2053
- // Reset the variant by adding the 3d back on
2054
- //
2055
- this.set({
2056
- variant: this.get('variant') + '3d',
2057
- shadow: prop_shadow,
2058
- labels: prop_labels,
2059
- labelsSticks: prop_labelsSticks
2060
- });
2061
-
2062
- // Necessary to allow method chaining
2063
- return this;
2064
- };
2065
-
2066
-
2067
-
2068
-
2069
- /**
2070
- * Pie chart explode
2071
- *
2072
- * Explodes the Pie chart - gradually incrementing the size of the chart.explode property
2073
- *
2074
- * @param object Options for the effect
2075
- * @param function An optional callback function to call when the animation completes
2076
- */
2077
- this.explode = function ()
2078
- {
2079
- var obj = this;
2080
- var opt = arguments[0] ? arguments[0] : {};
2081
- var callback = arguments[1] ? arguments[1] : function () {};
2082
- var frames = opt.frames ? opt.frames : 30;
2083
- var frame = 0;
2084
- var maxExplode = Number(typeof opt.radius === 'number' ? opt.radius : ma.max(ca.width, ca.height));
2085
- var currentExplode = Number(obj.get('exploded')) || 0;
2086
- var step = (maxExplode - currentExplode) / frames;
2087
-
2088
- // chart.exploded
2089
- var iterator = function ()
2090
- {
2091
- obj.set('exploded', currentExplode + (step * frame) );
2092
-
2093
- RGraph.clear(obj.canvas);
2094
- RGraph.redrawCanvas(obj.canvas);
2095
-
2096
- if (frame++ < frames) {
2097
- RGraph.Effects.updateCanvas(iterator);
2098
- } else {
2099
- callback(obj);
2100
- }
2101
- }
2102
-
2103
- iterator();
2104
-
2105
- return this;
2106
- };
2107
-
2108
-
2109
-
2110
-
2111
- /**
2112
- * Pie chart grow
2113
- *
2114
- * Gradually increases the pie chart radius
2115
- *
2116
- * @param object OPTIONAL An object of options
2117
- * @param function OPTIONAL A callback function
2118
- */
2119
- this.grow = function ()
2120
- {
2121
- var obj = this;
2122
- var canvas = obj.canvas;
2123
- var opt = arguments[0] ? arguments[0] : {};
2124
- var frames = opt.frames || 30;
2125
- var frame = 0;
2126
- var callback = arguments[1] ? arguments[1] : function () {};
2127
- var radius = obj.getRadius();
2128
-
2129
-
2130
- prop['chart.radius'] = 0;
2131
-
2132
- var iterator = function ()
2133
- {
2134
- obj.set('chart.radius', (frame / frames) * radius);
2135
-
2136
- RG.redrawCanvas(ca);
2137
-
2138
- if (frame++ < frames) {
2139
- RG.Effects.updateCanvas(iterator);
2140
-
2141
- } else {
2142
-
2143
- RG.redrawCanvas(obj.canvas);
2144
-
2145
-
2146
- callback(obj);
2147
- }
2148
- };
2149
-
2150
- iterator();
2151
-
2152
- return this;
2153
- };
2154
-
2155
-
2156
-
2157
-
2158
-
2159
- /**
2160
- * RoundRobin
2161
- *
2162
- * This effect does two things:
2163
- * 1. Gradually increases the size of each segment
2164
- * 2. Gradually increases the size of the radius from 0
2165
- *
2166
- * @param object OPTIONAL Options for the effect
2167
- * @param function OPTIONAL A callback function
2168
- */
2169
- this.roundrobin =
2170
- this.roundRobin = function ()
2171
- {
2172
- var obj = this,
2173
- opt = arguments[0] || {},
2174
- callback = arguments[1] || function () {},
2175
- frame = 0,
2176
- frames = opt.frames || 30,
2177
- radius = obj.getRadius(),
2178
- labels = obj.get('labels')
2179
-
2180
- obj.Set('chart.events', false);
2181
- obj.Set('chart.labels', []);
2182
-
2183
- var iterator = function ()
2184
- {
2185
- obj.set(
2186
- 'effect.roundrobin.multiplier',
2187
- RG.Effects.getEasingMultiplier(frames, frame)
2188
- );
2189
-
2190
- RGraph.redrawCanvas(ca);
2191
-
2192
- if (frame++ < frames) {
2193
- RGraph.Effects.updateCanvas(iterator);
2194
-
2195
- } else {
2196
-
2197
- obj.set({
2198
- events: true,
2199
- labels: labels
2200
- });
2201
-
2202
- RG.redrawCanvas(obj.canvas);
2203
- callback(obj);
2204
- }
2205
- };
2206
-
2207
- iterator();
2208
-
2209
- return this;
2210
- };
2211
-
2212
-
2213
-
2214
-
2215
- RG.att(ca);
2216
-
2217
-
2218
-
2219
-
2220
-
2221
-
2222
-
2223
-
2224
-
2225
- /**
2226
- * Pie chart implode
2227
- *
2228
- * Implodes the Pie chart - gradually decreasing the size of the chart.explode property. It starts at the largest of
2229
- * the canvas width./height
2230
- *
2231
- * @param object Optional options for the effect. You can pass in frames here - such as:
2232
- * myPie.implode({frames: 60}; function () {alert('Done!');})
2233
- * @param function A callback function which is called when the effect is finished
2234
- */
2235
- this.implode = function ()
2236
- {
2237
- var obj = this,
2238
- opt = arguments[0] || {},
2239
- callback = arguments[1] || function (){},
2240
- frames = opt.frames || 30,
2241
- frame = 0,
2242
- explodedMax = ma.max(ca.width, ca.height),
2243
- exploded = explodedMax;
2244
-
2245
-
2246
-
2247
- function iterator ()
2248
- {
2249
- exploded = explodedMax - ((frame / frames) * explodedMax);
2250
-
2251
- // Set the new value
2252
- obj.Set('exploded', exploded);
2253
-
2254
- RG.clear(ca);
2255
- RG.redrawCanvas(ca);
2256
-
2257
- if (frame++ < frames) {
2258
- RG.Effects.updateCanvas(iterator);
2259
- } else {
2260
- RG.clear(obj.canvas);
2261
- RG.redrawCanvas(obj.canvas);
2262
- callback(obj);
2263
- }
2264
- }
2265
-
2266
- iterator();
2267
-
2268
- return this;
2269
- };
2270
-
2271
-
2272
-
2273
-
2274
- /**
2275
- * Now need to register all chart types. MUST be after the setters/getters are defined
2276
- */
2277
- RG.register(this);
2278
-
2279
-
2280
-
2281
-
2282
- /**
2283
- * This is the 'end' of the constructor so if the first argument
2284
- * contains configuration data - handle that.
2285
- */
2286
- if (parseConfObjectForOptions) {
2287
- RG.parseObjectStyleConfig(this, conf.options);
2288
- }
2289
- };
2
+ RGraph=window.RGraph||{isRGraph:true};RGraph.Pie=function(conf)
3
+ {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var id=conf.id,canvas=document.getElementById(id),data=conf.data,parseConfObjectForOptions=true;}else{var id=conf,canvas=document.getElementById(id),data=arguments[1];}
4
+ this.id=id;this.canvas=canvas;this.context=this.canvas.getContext?this.canvas.getContext("2d",{alpha:(typeof id==='object'&&id.alpha===false)?false:true}):null;this.canvas.__object__=this;this.total=0;this.subTotal=0;this.angles=[];this.data=data;this.properties=[];this.type='pie';this.isRGraph=true;this.coords=[];this.coords.key=[];this.coordsSticks=[];this.coordsText=[];this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.original_colors=[];this.firstDraw=true;this.exploding=null;for(var i=0;i<this.data.length;++i){if(typeof this.data[i]==='string'){this.data[i]=parseFloat(this.data[i]);}}
5
+ this.properties={'chart.centerx.adjust':0,'chart.centery.adjust':0,'chart.colors':['red','#ccc','#cfc','blue','pink','yellow','black','orange','cyan','purple','#78CAEA','#E284E9','white','blue','#9E7BF6'],'chart.strokestyle':'white','chart.linewidth':3,'chart.labels':[],'chart.labels.bold':false,'chart.labels.sticks':false,'chart.labels.sticks.length':7,'chart.labels.sticks.colors':null,'chart.labels.sticks.usecolors':false,'chart.labels.sticks.linewidth':1,'chart.labels.sticks.hlength':5,'chart.labels.sticks.list':false,'chart.labels.ingraph':null,'chart.labels.ingraph.color':null,'chart.labels.ingraph.font':null,'chart.labels.ingraph.size':null,'chart.labels.ingraph.bounding':true,'chart.labels.ingraph.bounding.fill':'white','chart.labels.ingraph.specific':null,'chart.labels.ingraph.units.pre':'','chart.labels.ingraph.units.post':'','chart.labels.ingraph.radius':null,'chart.labels.center':null,'chart.labels.center.size':26,'chart.labels.center.font':'Segoe UI, Arial, Verdana, sans-serif','chart.labels.center.color':'black','chart.labels.center.italic':false,'chart.labels.center.bold':false,'chart.labels.center.units.pre':'','chart.labels.center.units.post':'','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.title':'','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':0.5,'chart.title.bold':true,'chart.title.font':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.shadow':true,'chart.shadow.color':'#aaa','chart.shadow.offsetx':0,'chart.shadow.offsety':0,'chart.shadow.blur':15,'chart.text.size':12,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.contextmenu':null,'chart.tooltips':null,'chart.tooltips.event':'onclick','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.highlight.style':'2d','chart.highlight.style.twod.fill':'rgba(255,255,255,0.7)','chart.highlight.style.twod.stroke':'rgba(255,255,255,0.7)','chart.highlight.style.outline.width':null,'chart.centerx':null,'chart.centery':null,'chart.radius':null,'chart.border':false,'chart.border.color':'rgba(255,255,255,0.5)','chart.key':null,'chart.key.background':'white','chart.key.position':'graph','chart.key.halign':'right','chart.key.shadow':false,'chart.key.shadow.color':'#666','chart.key.shadow.blur':3,'chart.key.shadow.offsetx':2,'chart.key.shadow.offsety':2,'chart.key.position.gutter.boxed':false,'chart.key.position.x':null,'chart.key.position.y':null,'chart.key.color.shape':'square','chart.key.rounded':true,'chart.key.linewidth':1,'chart.key.colors':null,'chart.key.interactive':false,'chart.key.interactive.highlight.chart.stroke':'black','chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black','chart.annotatable':false,'chart.annotate.color':'black','chart.zoom.factor':1.5,'chart.zoom.fade.in':true,'chart.zoom.fade.out':true,'chart.zoom.hdir':'right','chart.zoom.vdir':'down','chart.zoom.frames':25,'chart.zoom.delay':16.666,'chart.zoom.shadow':true,'chart.zoom.background':true,'chart.zoom.action':'zoom','chart.resizable':false,'chart.resize.handle.adjust':[0,0],'chart.resize.handle.background':null,'chart.variant':'pie','chart.variant.donut.width':null,'chart.variant.threed.depth':20,'chart.exploded':[],'chart.effect.roundrobin.multiplier':1,'chart.events.click':null,'chart.events.mousemove':null,'chart.centerpin':null,'chart.centerpin.fill':'gray','chart.centerpin.stroke':'white','chart.origin':0-(Math.PI/2),'chart.events':true,'chart.labels.colors':[],'chart.clearto':'rgba(0,0,0,0)'}
6
+ for(var i=0,len=data.length;i<len;i++){this.total+=data[i];this['$'+i]={};}
7
+ if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
8
+ var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
9
+ if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
10
+ this.set=this.Set=function(name)
11
+ {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
12
+ if(name.substr(0,6)!='chart.'){name='chart.'+name;}
13
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
14
+ if(name=='chart.highlight.style.twod.color'){name='chart.highlight.style.twod.fill';}
15
+ if(name=='chart.labels.spaced'){name='chart.labels.sticks.list';}
16
+ prop[name]=value;return this;};this.get=this.Get=function(name)
17
+ {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
18
+ while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
19
+ if(name=='chart.highlight.style.twod.color'){name='chart.highlight.style.twod.fill';}
20
+ return prop[name];};this.draw=this.Draw=function()
21
+ {RG.FireCustomEvent(this,'onbeforedraw');this.gutterLeft=prop['chart.gutter.left'];this.gutterRight=prop['chart.gutter.right'];this.gutterTop=prop['chart.gutter.top'];this.gutterBottom=prop['chart.gutter.bottom'];this.radius=this.getRadius();this.centerx=(this.graph.width/2)+this.gutterLeft+prop['chart.centerx.adjust'];this.centery=(this.graph.height/2)+this.gutterTop+prop['chart.centery.adjust'];this.subTotal=this.properties['chart.origin'];this.angles=[];this.coordsText=[];if(typeof prop['chart.radius']==='number')this.radius=prop['chart.radius'];if(typeof prop['chart.centerx']==='number')this.centerx=prop['chart.centerx'];if(typeof prop['chart.centery']==='number')this.centery=prop['chart.centery'];if(this.radius<=0){return;}
22
+ if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
23
+ if(prop['chart.labels.colors'].length<prop['chart.labels'].length){while(prop['chart.labels.colors'].length<prop['chart.labels'].length){prop['chart.labels.colors'].push(prop['chart.labels.colors'][prop['chart.labels.colors'].length-1]);}}else{if(typeof prop['chart.labels.colors']==='undefined'){prop['chart.labels.colors']=[];}
24
+ while(prop['chart.labels.colors'].length<prop['chart.labels'].length){prop['chart.labels.colors'].push(prop['chart.text.color']);}}
25
+ if(prop['chart.variant'].indexOf('3d')>0){return this.draw3d();}
26
+ RG.DrawTitle(this,prop['chart.title'],(ca.height/2)-this.radius-5,this.centerx,prop['chart.title.size']?prop['chart.title.size']:prop['chart.text.size']+2);this.total=RG.array_sum(this.data);var tot=this.total;var data=this.data;for(var i=0,len=this.data.length;i<len;i++){var angle=((data[i]/tot)*RG.TWOPI);this.DrawSegment(angle,prop['chart.colors'][i],i==(len-1),i);}
27
+ RG.NoShadow(this);if(prop['chart.linewidth']>0){this.DrawBorders();}
28
+ var len=this.angles.length;var r=this.radius;for(var action=0;action<2;action+=1){for(var i=0;i<len;i++){co.beginPath();var segment=this.angles[i];if(action===1){co.strokeStyle=typeof(prop['chart.strokestyle'])=='object'?prop['chart.strokestyle'][i]:prop['chart.strokestyle'];}
29
+ prop['chart.colors'][i]?co.fillStyle=prop['chart.colors'][i]:null;co.lineJoin='round';co.arc(segment[2],segment[3],r,(segment[0]),(segment[1]),false);if(prop['chart.variant']=='donut'){co.arc(segment[2],segment[3],typeof(prop['chart.variant.donut.width'])=='number'?r-prop['chart.variant.donut.width']:r/2,(segment[1]),(segment[0]),true);}else{co.lineTo(segment[2],segment[3]);}
30
+ co.closePath();action===0?co.fill():co.stroke();}}
31
+ if(prop['chart.labels.sticks']){this.DrawSticks();var strokeStyle=prop['chart.strokestyle'];}
32
+ if(prop['chart.labels']){this.DrawLabels();}
33
+ if(prop['chart.centerpin']){this.DrawCenterpin();}
34
+ if(prop['chart.labels.ingraph']){this.DrawInGraphLabels();}
35
+ if(!RG.isNull(prop['chart.labels.center'])){this.drawCenterLabel(prop['chart.labels.center']);}
36
+ if(prop['chart.contextmenu']){RG.ShowContext(this);}
37
+ if(prop['chart.border']){co.beginPath();co.lineWidth=5;co.strokeStyle=prop['chart.border.color'];co.arc(this.centerx,this.centery,this.radius-2,0,RG.TWOPI,0);co.stroke();}
38
+ if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
39
+ RG.NoShadow(this);if(prop['chart.resizable']){RG.AllowResizing(this);}
40
+ if(prop['chart.events']==true){RG.InstallEventListeners(this);}
41
+ if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
42
+ RG.FireCustomEvent(this,'ondraw');return this;};this.exec=function(func)
43
+ {func(this);return this;};this.drawSegment=this.DrawSegment=function(radians,color,last,index)
44
+ {if(RGraph.ISOLD&&radians==RG.TWOPI){radians-=0.0001;}else if(RGraph.ISOLD&&radians==0){radians=0.001;}
45
+ var subTotal=this.subTotal;radians=radians*prop['chart.effect.roundrobin.multiplier'];co.beginPath();color?co.fillStyle=color:null;co.strokeStyle=prop['chart.strokestyle'];co.lineWidth=0;if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}
46
+ if((typeof(prop['chart.exploded'])=='object'&&prop['chart.exploded'][index]>0)||typeof(prop['chart.exploded'])=='number'){var explosion=typeof(prop['chart.exploded'])=='number'?prop['chart.exploded']:prop['chart.exploded'][index];var x=0;var y=0;var h=explosion;var t=subTotal+(radians/2);var x=(Math.cos(t)*explosion);var y=(Math.sin(t)*explosion);var r=this.radius;co.moveTo(this.centerx+x,this.centery+y);}else{var x=0;var y=0;var r=this.radius;}
47
+ var startAngle=subTotal;var endAngle=((subTotal+radians));co.arc(this.centerx+x,this.centery+y,r,startAngle,endAngle,0);if(prop['chart.variant']=='donut'){co.arc(this.centerx+x,this.centery+y,typeof(prop['chart.variant.donut.width'])=='number'?r-prop['chart.variant.donut.width']:r/2,endAngle,startAngle,true);}else{co.lineTo(this.centerx+x,this.centery+y);}
48
+ co.closePath();this.angles.push([subTotal,subTotal+radians,this.centerx+x,this.centery+y]);co.fill();this.subTotal+=radians;};this.drawLabels=this.DrawLabels=function()
49
+ {if(prop['chart.labels'].length&&prop['chart.labels.sticks.list']){return this.drawLabelsList();}
50
+ var hAlignment='left',vAlignment='center',labels=prop['chart.labels'],context=co,font=prop['chart.text.font'],bold=prop['chart.labels.bold'],text_size=prop['chart.text.size'],cx=this.centerx,cy=this.centery,r=this.radius;RG.noShadow(this);co.fillStyle='black';co.beginPath();if(labels&&labels.length){for(i=0;i<this.angles.length;++i){var segment=this.angles[i];if(typeof labels[i]!='string'&&typeof labels[i]!='number'){continue;}
51
+ co.moveTo(cx,cy);var a=segment[0]+((segment[1]-segment[0])/2),angle=((segment[1]-segment[0])/2)+segment[0];if(typeof prop['chart.exploded']==='object'&&prop['chart.exploded'][i]||typeof prop['chart.exploded']=='number'){var t=((segment[1]-segment[0])/2),seperation=typeof(prop['chart.exploded'])=='number'?prop['chart.exploded']:prop['chart.exploded'][i];var explosion_offsetx=(Math.cos(angle)*seperation),explosion_offsety=(Math.sin(angle)*seperation);}else{var explosion_offsetx=0,explosion_offsety=0;}
52
+ if(prop['chart.labels.sticks']){explosion_offsetx+=(ma.cos(angle)*(typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length']));explosion_offsety+=(ma.sin(angle)*(typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length']));}
53
+ var x=cx+explosion_offsetx+((r+10)*Math.cos(a))+(prop['chart.labels.sticks']?(a<RG.HALFPI||a>(RG.TWOPI+RG.HALFPI)?2:-2):0),y=cy+explosion_offsety+(((r+10)*Math.sin(a)));if(this.coordsSticks&&this.coordsSticks[i]){var x=this.coordsSticks[i][4][0]+(x<cx?-5:5),y=this.coordsSticks[i][4][1];}
54
+ vAlignment='center';hAlignment=x<cx?'right':'left';co.fillStyle=prop['chart.text.color'];if(typeof prop['chart.labels.colors']==='object'&&prop['chart.labels.colors']&&prop['chart.labels.colors'][i]){co.fillStyle=prop['chart.labels.colors'][i];}
55
+ RG.text2(this,{font:font,size:text_size,x:x,y:y,text:labels[i],valign:vAlignment,halign:hAlignment,tag:'labels',bold:bold,color:prop['chart.labels.sticks.usecolors']?prop['chart.colors'][i]:'black'});}
56
+ co.fill();}};this.drawLabelsList=function()
57
+ {var segment=this.angles[i],labels=prop['chart.labels'],labels_right=[],labels_left=[],text_font=prop['chart.text.font'],text_size=prop['chart.text.size'],text_color=prop['chart.text.color'],left=[],right=[],centerx=this.centerx,centery=this.centery,radius=this.radius,offset=50
58
+ for(var i=0;i<this.angles.length;++i){var angle=this.angles[i][0]+((this.angles[i][1]-this.angles[i][0])/2),endpoint_inner=RG.getRadiusEndPoint(centerx,centery,angle,radius+5),endpoint_outer=RG.getRadiusEndPoint(centerx,centery,angle,radius+10),explosion=[(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i]),(ma.cos(angle)*(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i])),(ma.sin(angle)*(typeof prop['chart.exploded']==='number'?prop['chart.exploded']:prop['chart.exploded'][i]))]
59
+ if(typeof prop['chart.labels.sticks.colors']==='object'&&prop['chart.labels.sticks.colors']&&prop['chart.labels.sticks.colors'][i]){var color=prop['chart.labels.sticks.colors'][i];}else if(prop['chart.labels.sticks.usecolors']&&prop['chart.colors'][i]){var color=prop['chart.colors'][i];}else{var color=prop['chart.text.color'];}
60
+ if(angle>(-1*RG.HALFPI)&&angle<RG.HALFPI){labels_right.push([i,angle,labels[i]?labels[i]:'',endpoint_inner,endpoint_outer,color,RG.arrayClone(explosion)]);}else{labels_left.push([i,angle,labels[i]?labels[i]:'',endpoint_inner,endpoint_outer,color,RG.arrayClone(explosion)]);}}
61
+ var vspace_right=(ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/labels_right.length
62
+ for(var i=0,y=(prop['chart.gutter.top']+(vspace_right/2));i<labels_right.length;y+=vspace_right,i++){if(labels_right[i][2]){var x=this.centerx+this.radius+offset,idx=labels_right[i][0],explosionX=labels_right[i][6][0]?labels_right[i][6][1]:0,explosionY=labels_right[i][6][0]?labels_right[i][6][2]:0
63
+ var ret=RG.text2(this,{font:text_font,size:text_size,x:x+explosionX,y:y+explosionY,text:labels_right[i][2],valign:'center',halign:'left',tag:'labels',color:labels_right[i][5]});if(ret&&ret.node){ret.node.__index__=labels_right[i][0];}
64
+ pa2(co,'lc round lw % b m % % l % % l % % l % % s %',prop['chart.labels.sticks.linewidth'],labels_right[i][3][0]+explosionX,labels_right[i][3][1]+explosionY,labels_right[i][4][0]+explosionX,labels_right[i][4][1]+explosionY,this.centerx+this.radius+25+explosionX,ma.round(labels_right[i][4][1]+explosionY),ret.x-5,ret.y+(ret.height/2),labels_right[i][5]);}}
65
+ var vspace_left=(ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/labels_left.length
66
+ for(var i=(labels_left.length-1),y=(prop['chart.gutter.top']+(vspace_left/2));i>=0;y+=vspace_left,i--){if(labels_left[i][2]){var x=this.centerx-this.radius-offset,idx=labels_left[i][0],explosionX=labels_left[i][6][0]?labels_left[i][6][1]:0,explosionY=labels_left[i][6][0]?labels_left[i][6][2]:0
67
+ var ret=RG.text2(this,{font:text_font,size:text_size,x:x+explosionX,y:y+explosionY,text:labels_left[i][2],valign:'center',halign:'right',tag:'labels',color:labels_left[i][5]});if(ret&&ret.node){ret.node.__index__=labels_left[i][0];}
68
+ pa2(co,'lw % b m % % l % % l % % l % % s %',prop['chart.labels.sticks.linewidth'],labels_left[i][3][0]+explosionX,labels_left[i][3][1]+explosionY,labels_left[i][4][0]+explosionX,labels_left[i][4][1]+explosionY,this.centerx-this.radius-25+explosionX,ma.round(labels_left[i][4][1]+explosionY),ret.x+5+ret.width,ret.y+(ret.height/2),labels_left[i][5]);}}};this.drawSticks=this.DrawSticks=function()
69
+ {var offset=prop['chart.linewidth']/2,exploded=prop['chart.exploded'],sticks=prop['chart.labels.sticks'],colors=prop['chart.colors'],cx=this.centerx,cy=this.centery,radius=this.radius,points=[],linewidth=prop['chart.labels.sticks.linewidth']
70
+ for(var i=0,len=this.angles.length;i<len;++i){var segment=this.angles[i];if(typeof sticks==='object'&&!sticks[i]){continue;}
71
+ var radians=segment[1]-segment[0];co.beginPath();co.strokeStyle=typeof prop['chart.labels.sticks.colors']==='string'?prop['chart.labels.sticks.colors']:(!RG.isNull(prop['chart.labels.sticks.colors'])?prop['chart.labels.sticks.colors'][i]:'gray');co.lineWidth=linewidth;if(typeof prop['chart.labels.sticks.color']==='string'){co.strokeStyle=prop['chart.labels.sticks.color'];}
72
+ if(prop['chart.labels.sticks.usecolors']){co.strokeStyle=prop['chart.colors'][i];}
73
+ var midpoint=(segment[0]+(radians/2));if(typeof exploded==='object'&&exploded[i]){var extra=exploded[i];}else if(typeof exploded==='number'){var extra=exploded;}else{var extra=0;}
74
+ var stickLength=typeof prop['chart.labels.sticks.length']==='object'?prop['chart.labels.sticks.length'][i]:prop['chart.labels.sticks.length'];points[0]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+extra+offset);points[1]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra-5);points[2]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra);points[3]=RG.getRadiusEndPoint(cx,cy,midpoint,radius+stickLength+extra);points[3][0]+=(points[3][0]>cx?5:-5);points[4]=[points[2][0]+(points[2][0]>cx?5+prop['chart.labels.sticks.hlength']:-5-prop['chart.labels.sticks.hlength']),points[2][1]];co.moveTo(points[0][0],points[0][1]);co.quadraticCurveTo(points[2][0],points[2][1],points[4][0],points[4][1]);co.stroke();this.coordsSticks[i]=[points[0],points[1],points[2],points[3],points[4]];}};this.getShape=this.getSegment=function(e)
75
+ {RG.FixEventObject(e);var accuracy=arguments[1]?arguments[1]:0;var canvas=ca;var context=co;var mouseCoords=RG.getMouseXY(e);var mouseX=mouseCoords[0];var mouseY=mouseCoords[1];var r=this.radius;var angles=this.angles;var ret=[];for(var i=0,len=angles.length;i<len;++i){co.beginPath();co.strokeStyle='rgba(0,0,0,0)';co.arc(angles[i][2],angles[i][3],this.radius,angles[i][0],angles[i][1],false);if(this.type=='pie'&&prop['chart.variant']=='donut'){co.arc(angles[i][2],angles[i][3],(typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:this.radius/2),angles[i][1],angles[i][0],true);}else{co.lineTo(angles[i][2],angles[i][3]);}
76
+ co.closePath();if(!co.isPointInPath(mouseX,mouseY)){continue;}
77
+ ret[0]=angles[i][2];ret[1]=angles[i][3];ret[2]=this.radius;ret[3]=angles[i][0]-RG.TWOPI;ret[4]=angles[i][1];ret[5]=i;if(ret[3]<0)ret[3]+=RG.TWOPI;if(ret[4]>RG.TWOPI)ret[4]-=RG.TWOPI;var tooltip=RG.parseTooltipText?RG.parseTooltipText(prop['chart.tooltips'],ret[5]):null;ret['object']=this;ret['x']=ret[0];ret['y']=ret[1];ret['radius']=ret[2];ret['angle.start']=ret[3];ret['angle.end']=ret[4];ret['index']=ret[5];ret['tooltip']=tooltip;return ret;}
78
+ return null;};this.drawBorders=this.DrawBorders=function()
79
+ {if(prop['chart.linewidth']>0){co.lineWidth=prop['chart.linewidth'];co.strokeStyle=prop['chart.strokestyle'];var r=this.radius;for(var i=0,len=this.angles.length;i<len;++i){var segment=this.angles[i];co.beginPath();co.arc(segment[2],segment[3],r,(segment[0]),(segment[0]+0.001),0);co.arc(segment[2],segment[3],prop['chart.variant']=='donut'?(typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:r/2):r,segment[0],segment[0]+0.0001,0);co.closePath();co.stroke();}}};this.getRadius=function()
80
+ {this.graph={width:ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'],height:ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom']}
81
+ if(typeof(prop['chart.radius'])=='number'){this.radius=prop['chart.radius'];}else{this.radius=Math.min(this.graph.width,this.graph.height)/2;}
82
+ return this.radius;};this.explodeSegment=this.Explode=function(index,size)
83
+ {if(typeof this.exploding==='number'&&this.exploding===index){return;}
84
+ if(!prop['chart.exploded']){prop['chart.exploded']=[];}
85
+ if(typeof(prop['chart.exploded'])=='number'){var original_explode=prop['chart.exploded'];var exploded=prop['chart.exploded'];prop['chart.exploded']=[];for(var i=0,len=this.data.length;i<len;++i){prop['chart.exploded'][i]=exploded;}}
86
+ prop['chart.exploded'][index]=typeof(original_explode)=='number'?original_explode:0;this.exploding=index;var delay=RG.ISIE&&!RG.ISIE10?25:16.666;for(var o=0;o<size;++o){setTimeout(function()
87
+ {prop['chart.exploded'][index]+=1;RG.Clear(ca);RG.RedrawCanvas(ca);},o*delay);}
88
+ var obj=this;setTimeout(function()
89
+ {obj.exploding=null;},size*delay);};this.highlight_segment=function(segment)
90
+ {co.beginPath();co.strokeStyle=prop['chart.highlight.style.twod.stroke'];co.fillStyle=prop['chart.highlight.style.twod.fill'];co.moveTo(segment[0],segment[1]);co.arc(segment[0],segment[1],segment[2],this.angles[segment[5]][0],this.angles[segment[5]][1],0);co.lineTo(segment[0],segment[1]);co.closePath();co.stroke();co.fill();};this.highlight=this.Highlight=function(shape)
91
+ {if(prop['chart.tooltips.highlight']){if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else if(prop['chart.highlight.style']=='3d'){co.lineWidth=1;var extent=2;co.beginPath();RG.NoShadow(this);co.fillStyle='rgba(0,0,0,0)';co.arc(shape['x'],shape['y'],shape['radius'],shape['angle.start'],shape['angle.end'],false);if(prop['chart.variant']=='donut'){co.arc(shape['x'],shape['y'],shape['radius']/5,shape['angle.end'],shape['angle.start'],true);}else{co.lineTo(shape['x'],shape['y']);}
92
+ co.closePath();co.fill();co.beginPath();co.shadowColor='#666';co.shadowBlur=3;co.shadowOffsetX=3;co.shadowOffsetY=3;co.fillStyle=prop['chart.colors'][shape['index']];co.strokeStyle=prop['chart.strokestyle'];co.arc(shape['x']-extent,shape['y']-extent,shape['radius'],shape['angle.start'],shape['angle.end'],false);if(prop['chart.variant']=='donut'){co.arc(shape['x']-extent,shape['y']-extent,shape['radius']/2,shape['angle.end'],shape['angle.start'],true)}else{co.lineTo(shape['x']-extent,shape['y']-extent);}
93
+ co.closePath();co.stroke();co.fill();RG.NoShadow(this);if(prop['chart.border']){co.beginPath();co.strokeStyle=prop['chart.border.color'];co.lineWidth=5;co.arc(shape['x']-extent,shape['y']-extent,shape['radius']-2,shape['angle.start'],shape['angle.end'],false);co.stroke();}}else if(prop['chart.highlight.style']==='outline'){var tooltip=RG.Registry.get('chart.tooltip'),index=tooltip.__index__,coords=this.angles[index],color=this.get('colors')[index]
94
+ width=this.radius/12.5;if(typeof prop['chart.highlight.style.outline.width']==='number'){width=prop['chart.highlight.style.outline.width'];}
95
+ RGraph.path2(co,'ga 0.25 b a % % % % % false a % % % % % true c f % ga 1',coords[2],coords[3],this.radius+2+width,coords[0],coords[1],coords[2],coords[3],this.radius+2,coords[1],coords[0],color);}else{co.beginPath();co.strokeStyle=prop['chart.highlight.style.twod.stroke'];co.fillStyle=prop['chart.highlight.style.twod.fill'];if(prop['chart.variant'].indexOf('donut')>-1){co.arc(shape['x'],shape['y'],shape['radius'],shape['angle.start'],shape['angle.end'],false);co.arc(shape['x'],shape['y'],typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:shape['radius']/2,shape['angle.end'],shape['angle.start'],true);}else{co.arc(shape['x'],shape['y'],shape['radius']+1,shape['angle.start'],shape['angle.end'],false);co.lineTo(shape['x'],shape['y']);}
96
+ co.closePath();co.stroke();co.fill();}}};this.getObjectByXY=function(e)
97
+ {if(this.getShape(e)){return this;}};this.drawCenterpin=this.DrawCenterpin=function()
98
+ {if(typeof(prop['chart.centerpin'])=='number'&&prop['chart.centerpin']>0){var cx=this.centerx;var cy=this.centery;co.beginPath();co.strokeStyle=prop['chart.centerpin.stroke']?prop['chart.centerpin.stroke']:prop['chart.strokestyle'];co.fillStyle=prop['chart.centerpin.fill']?prop['chart.centerpin.fill']:prop['chart.strokestyle'];co.moveTo(cx,cy);co.arc(cx,cy,prop['chart.centerpin'],0,RG.TWOPI,false);co.stroke();co.fill();}};this.drawInGraphLabels=this.DrawInGraphLabels=function()
99
+ {var context=co;var cx=this.centerx;var cy=this.centery;var radius=prop['chart.labels.ingraph.radius'];if(radius<=2&&radius>0){radiusFactor=radius;}else{radiusFactor=0.5;}
100
+ if(prop['chart.variant']=='donut'){var r=this.radius*(0.5+(radiusFactor*0.5));if(typeof(prop['chart.variant.donut.width'])=='number'){var r=(this.radius-prop['chart.variant.donut.width'])+(prop['chart.variant.donut.width']/2);}}else{var r=this.radius*radiusFactor;}
101
+ if(radius>2){r=radius;}
102
+ for(var i=0,len=this.angles.length;i<len;++i){if(typeof(prop['chart.exploded'])=='object'&&typeof(prop['chart.exploded'][i])=='number'){var explosion=prop['chart.exploded'][i];}else if(typeof(prop['chart.exploded'])=='number'){var explosion=parseInt(prop['chart.exploded']);}else{var explosion=0;}
103
+ var angleStart=this.angles[i][0];var angleEnd=this.angles[i][1];var angleCenter=((angleEnd-angleStart)/2)+angleStart;var coords=RG.getRadiusEndPoint(this.centerx,this.centery,angleCenter,r+(explosion?explosion:0));var x=coords[0];var y=coords[1];var text=prop['chart.labels.ingraph.specific']&&typeof(prop['chart.labels.ingraph.specific'][i])=='string'?prop['chart.labels.ingraph.specific'][i]:RG.number_format(this,this.data[i],prop['chart.labels.ingraph.units.pre'],prop['chart.labels.ingraph.units.post']);if(text){co.beginPath();var font=typeof prop['chart.labels.ingraph.font']==='string'?prop['chart.labels.ingraph.font']:prop['chart.text.font'];var size=typeof prop['chart.labels.ingraph.size']==='number'?prop['chart.labels.ingraph.size']:prop['chart.text.size']+2;co.fillStyle=prop['chart.labels.ingraph.color']?prop['chart.labels.ingraph.color']:'black';RG.Text2(this,{'font':font,'size':size,'x':x,'y':y,'text':text,'valign':'center','halign':'center','bounding':prop['chart.labels.ingraph.bounding'],'bounding.fill':prop['chart.labels.ingraph.bounding.fill'],'tag':'labels.ingraph'});co.stroke();}}};this.drawCenterLabel=function(label)
104
+ {var font=prop['chart.labels.center.font'],size=prop['chart.labels.center.size'],color=prop['chart.labels.center.color'],unitsPre=prop['chart.labels.center.units.pre'],unitsPost=prop['chart.labels.center.units.post'],bold=prop['chart.labels.center.bold'],italic=prop['chart.labels.center.italic'];RG.text2(this,{color:color,bold:bold,italic:italic,font:font,size:size,x:this.centerx,y:this.centery,halign:'center',valign:'center',text:RG.numberFormat(this,label,unitsPre,unitsPost)});}
105
+ this.getAngle=function(value)
106
+ {if(value>this.total){return null;}
107
+ var angle=(value/this.total)*RG.TWOPI;angle+=prop['chart.origin'];return angle;};this.parseColors=function()
108
+ {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.arrayClone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.arrayClone(prop['chart.key.colors']);this.original_colors['chart.strokestyle']=RG.arrayClone(prop['chart.strokestyle']);this.original_colors['chart.highlight.stroke']=RG.arrayClone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.style.twod.fill']=RG.arrayClone(prop['chart.highlight.style.twod.fill']);this.original_colors['chart.highlight.style.twod.stroke']=RG.arrayClone(prop['chart.highlight.style.twod.stroke']);this.original_colors['chart.ingraph.bounding.fill']=RG.arrayClone(prop['chart.ingraph.bounding.fill']);this.original_colors['chart.ingraph.color']=RG.arrayClone(prop['chart.ingraph.color']);}
109
+ for(var i=0;i<prop['chart.colors'].length;++i){prop['chart.colors'][i]=this.parseSingleColorForGradient(prop['chart.colors'][i]);}
110
+ var keyColors=prop['chart.key.colors'];if(keyColors){for(var i=0;i<keyColors.length;++i){keyColors[i]=this.parseSingleColorForGradient(keyColors[i]);}}
111
+ prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.style.twod.fill']=this.parseSingleColorForGradient(prop['chart.highlight.style.twod.fill']);prop['chart.highlight.style.twod.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.style.twod.stroke']);prop['chart.labels.ingraph.bounding.fill']=this.parseSingleColorForGradient(prop['chart.labels.ingraph.bounding.fill']);prop['chart.labels.ingraph.color']=this.parseSingleColorForGradient(prop['chart.labels.ingraph.color']);};this.reset=function()
112
+ {};this.parseSingleColorForGradient=function(color)
113
+ {if(!color||typeof(color)!='string'){return color;}
114
+ if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');if(prop['chart.variant']=='donut'){var radius_start=typeof(prop['chart.variant.donut.width'])=='number'?this.radius-prop['chart.variant.donut.width']:this.radius/2;}else{var radius_start=0;}
115
+ var grad=co.createRadialGradient(this.centerx,this.centery,radius_start,this.centerx,this.centery,Math.min(ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'],ca.height-prop['chart.gutter.top']-prop['chart.gutter.bottom'])/2);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
116
+ return grad?grad:color;};this.interactiveKeyHighlight=function(index)
117
+ {if(this.angles&&this.angles[index]){var segment=this.angles[index];var x=segment[2];var y=segment[3];var start=segment[0];var end=segment[1];co.strokeStyle=prop['chart.key.interactive.highlight.chart.stroke'];co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.lineWidth=2;co.lineJoin='bevel';co.beginPath();co.moveTo(x,y);co.arc(x,y,this.radius,start,end,false);co.closePath();co.fill();co.stroke();}};this.on=function(type,func)
118
+ {if(type.substr(0,2)!=='on'){type='on'+type;}
119
+ if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
120
+ return this;};this.firstDrawFunc=function()
121
+ {};this.draw3d=function()
122
+ {var scaleX=1.5,depth=prop['chart.variant.threed.depth'],prop_shadow=prop['chart.shadow'],prop_labels=prop['chart.labels'],prop_labelsSticks=prop['chart.labels.sticks']
123
+ this.set({labels:[],labelsSticks:false,strokestyle:'rgba(0,0,0,0)'});this.set({variant:this.get('variant').replace(/3d/,'')});this.context.setTransform(scaleX,0,0,1,(ca.width*(scaleX)-ca.width)* -0.5,0);for(var i=depth;i>0;i-=1){this.set({centeryAdjust:i});if(i===parseInt(depth/2)){this.set({labels:prop_labels,labelsSticks:prop_labelsSticks});}
124
+ if(i===0){this.set({shadow:prop_shadow});}
125
+ this.draw();this.set('shadow',false);if(i<=parseInt(depth/2)){this.set({labels:[],labelsSticks:false});}
126
+ if(i>1){if(prop['chart.variant'].indexOf('donut')!==-1){for(var j=0;j<this.angles.length;++j){pa2(co,['b','a',this.angles[j][2],this.angles[j][3],this.radius+1,this.angles[j][0],this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],false,'a',this.angles[j][2],this.angles[j][3],this.radius/2,this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],this.angles[j][0],true,'f','rgba(0,0,0,0.15)']);}}else{for(var j=0;j<this.angles.length;++j){pa2(co,['b','m',this.angles[j][2],this.angles[j][3],'a',this.angles[j][2],this.angles[j][3],this.radius+1,this.angles[j][0],this.angles[j][1]*prop['chart.effect.roundrobin.multiplier'],false,'c','f','rgba(0,0,0,0.15)']);}}}}
127
+ this.set({variant:this.get('variant')+'3d',shadow:prop_shadow,labels:prop_labels,labelsSticks:prop_labelsSticks});return this;};this.explode=function()
128
+ {var obj=this;var opt=arguments[0]?arguments[0]:{};var callback=arguments[1]?arguments[1]:function(){};var frames=opt.frames?opt.frames:30;var frame=0;var maxExplode=Number(typeof opt.radius==='number'?opt.radius:ma.max(ca.width,ca.height));var currentExplode=Number(obj.get('exploded'))||0;var step=(maxExplode-currentExplode)/frames;var iterator=function()
129
+ {obj.set('exploded',currentExplode+(step*frame));RGraph.clear(obj.canvas);RGraph.redrawCanvas(obj.canvas);if(frame++<frames){RGraph.Effects.updateCanvas(iterator);}else{callback(obj);}}
130
+ iterator();return this;};this.grow=function()
131
+ {var obj=this;var canvas=obj.canvas;var opt=arguments[0]?arguments[0]:{};var frames=opt.frames||30;var frame=0;var callback=arguments[1]?arguments[1]:function(){};var radius=obj.getRadius();prop['chart.radius']=0;var iterator=function()
132
+ {obj.set('chart.radius',(frame/frames)*radius);RG.redrawCanvas(ca);if(frame++<frames){RG.Effects.updateCanvas(iterator);}else{RG.redrawCanvas(obj.canvas);callback(obj);}};iterator();return this;};this.roundrobin=this.roundRobin=function()
133
+ {var obj=this,opt=arguments[0]||{},callback=arguments[1]||function(){},frame=0,frames=opt.frames||30,radius=obj.getRadius(),labels=obj.get('labels')
134
+ obj.Set('chart.events',false);obj.Set('chart.labels',[]);var iterator=function()
135
+ {obj.set('effect.roundrobin.multiplier',RG.Effects.getEasingMultiplier(frames,frame));RGraph.redrawCanvas(ca);if(frame++<frames){RGraph.Effects.updateCanvas(iterator);}else{obj.set({events:true,labels:labels});RG.redrawCanvas(obj.canvas);callback(obj);}};iterator();return this;};RG.att(ca);this.implode=function()
136
+ {var obj=this,opt=arguments[0]||{},callback=arguments[1]||function(){},frames=opt.frames||30,frame=0,explodedMax=ma.max(ca.width,ca.height),exploded=explodedMax;function iterator()
137
+ {exploded=explodedMax-((frame/frames)*explodedMax);obj.Set('exploded',exploded);RG.clear(ca);RG.redrawCanvas(ca);if(frame++<frames){RG.Effects.updateCanvas(iterator);}else{RG.clear(obj.canvas);RG.redrawCanvas(obj.canvas);callback(obj);}}
138
+ iterator();return this;};RG.register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};