source: Dev/branches/jQueryUI/client/RGraph/libraries/RGraph.pie.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 33.8 KB
Line 
1/**
2    * o------------------------------------------------------------------------------o
3    * | This file is part of the RGraph package - you can learn more at:             |
4    * |                                                                              |
5    * |                          http://www.rgraph.net                               |
6    * |                                                                              |
7    * | This package is licensed under the RGraph license. For all kinds of business |
8    * | purposes there is a small one-time licensing fee to pay and for non          |
9    * | commercial  purposes it is free to use. You can read the full license here:  |
10    * |                                                                              |
11    * |                      http://www.rgraph.net/LICENSE.txt                       |
12    * o------------------------------------------------------------------------------o
13    */
14   
15    if (typeof(RGraph) == 'undefined') RGraph = {};
16
17    /**
18    * The pie chart constructor
19    *
20    * @param data array The data to be represented on the pie chart
21    */
22    RGraph.Pie = function (id, data)
23    {
24        this.id                = id;
25        this.canvas            = document.getElementById(id);
26        this.context           = this.canvas.getContext("2d");
27        this.canvas.__object__ = this;
28        this.total             = 0;
29        this.subTotal          = 0;
30        this.angles            = [];
31        this.data              = data;
32        this.properties        = [];
33        this.type              = 'pie';
34        this.isRGraph          = true;
35
36
37        /**
38        * Compatibility with older browsers
39        */
40        RGraph.OldBrowserCompat(this.context);
41
42        this.properties = {
43            'chart.colors':                 ['rgb(255,0,0)', '#ddd', 'rgb(0,255,0)', 'rgb(0,0,255)', 'pink', 'yellow', '#000'],
44            'chart.strokestyle':            '#999',
45            'chart.linewidth':              1,
46            'chart.labels':                 [],
47            'chart.labels.sticks':          false,
48            'chart.labels.sticks.color':    '#aaa',
49            'chart.segments':               [],
50            'chart.gutter.left':            25,
51            'chart.gutter.right':           25,
52            'chart.gutter.top':             25,
53            'chart.gutter.bottom':          25,
54            'chart.title':                  '',
55            'chart.title.background':       null,
56            'chart.title.hpos':             null,
57            'chart.title.vpos':             null,
58            'chart.shadow':                 false,
59            'chart.shadow.color':           'rgba(0,0,0,0.5)',
60            'chart.shadow.offsetx':         3,
61            'chart.shadow.offsety':         3,
62            'chart.shadow.blur':            3,
63            'chart.text.size':              10,
64            'chart.text.color':             'black',
65            'chart.text.font':              'Verdana',
66            'chart.contextmenu':            null,
67            'chart.tooltips':               [],
68            'chart.tooltips.event':         'onclick',
69            'chart.tooltips.effect':        'fade',
70            'chart.tooltips.css.class':     'RGraph_tooltip',
71            'chart.tooltips.highlight':     true,
72            'chart.highlight.style':        '3d',
73            'chart.highlight.style.2d.fill': 'rgba(255,255,255,0.5)',
74            'chart.highlight.style.2d.stroke': 'rgba(255,255,255,0)',
75            'chart.radius':                 null,
76            'chart.border':                 false,
77            'chart.border.color':           'rgba(255,255,255,0.5)',
78            'chart.key':                    null,
79            'chart.key.background':         'white',
80            'chart.key.position':           'graph',
81            'chart.key.halign':             'right',
82            'chart.key.shadow':             false,
83            'chart.key.shadow.color':       '#666',
84            'chart.key.shadow.blur':        3,
85            'chart.key.shadow.offsetx':     2,
86            'chart.key.shadow.offsety':     2,
87            'chart.key.position.gutter.boxed': true,
88            'chart.key.position.x':         null,
89            'chart.key.position.y':         null,
90            'chart.key.color.shape':        'square',
91            'chart.key.rounded':            true,
92            'chart.key.linewidth':          1,
93            'chart.annotatable':            false,
94            'chart.annotate.color':         'black',
95            'chart.align':                  'center',
96            'chart.zoom.factor':            1.5,
97            'chart.zoom.fade.in':           true,
98            'chart.zoom.fade.out':          true,
99            'chart.zoom.hdir':              'right',
100            'chart.zoom.vdir':              'down',
101            'chart.zoom.frames':            10,
102            'chart.zoom.delay':             50,
103            'chart.zoom.shadow':            true,
104            'chart.zoom.mode':              'canvas',
105            'chart.zoom.thumbnail.width':   75,
106            'chart.zoom.thumbnail.height':  75,
107            'chart.zoom.background':        true,
108            'chart.zoom.action':            'zoom',
109            'chart.resizable':              false,
110            'chart.resize.handle.adjust':   [0,0],
111            'chart.resize.handle.background': null,
112            'chart.variant':                'pie',
113            'chart.variant.donut.color':    'white',
114            'chart.exploded':               []
115        }
116
117        /**
118        * Calculate the total
119        */
120        for (var i=0,len=data.length; i<len; i++) {
121            this.total += data[i];
122        }
123
124
125        /**
126        * Set the .getShape commonly named method
127        */
128        this.getShape = this.getSegment;
129    }
130
131
132    /**
133    * A generic setter
134    */
135    RGraph.Pie.prototype.Set = function (name, value)
136    {
137        if (name == 'chart.highlight.style.2d.color') {
138            name = 'chart.highlight.style.2d.fill';
139        }
140
141        this.properties[name] = value;
142    }
143
144
145    /**
146    * A generic getter
147    */
148    RGraph.Pie.prototype.Get = function (name)
149    {
150        if (name == 'chart.highlight.style.2d.color') {
151            name = 'chart.highlight.style.2d.fill';
152        }
153
154        return this.properties[name];
155    }
156
157
158    /**
159    * This draws the pie chart
160    */
161    RGraph.Pie.prototype.Draw = function ()
162    {
163        /**
164        * Fire the onbeforedraw event
165        */
166        RGraph.FireCustomEvent(this, 'onbeforedraw');
167
168       
169        /**
170        * This bit of code converts chart.exploded from an integer to an array
171        * that consists of that value, repeated n times, where n is equal to
172        * the number of segments that you have
173        */
174        var explosion = this.Get('chart.exploded');
175        if (typeof(explosion) == 'number') {
176            this.Set('chart.exploded', RGraph.array_pad([], this.data.length, explosion));
177        }
178
179        /**
180        * This is new in May 2011 and facilitates indiviual gutter settings,
181        * eg chart.gutter.left
182        */
183        this.gutterLeft   = this.Get('chart.gutter.left');
184        this.gutterRight  = this.Get('chart.gutter.right');
185        this.gutterTop    = this.Get('chart.gutter.top');
186        this.gutterBottom = this.Get('chart.gutter.bottom');
187
188        /**
189        * Reset this to an empty array
190        */
191        this.Set('chart.segments', []);
192
193        /**
194        * Clear all of this canvases event handlers (the ones installed by RGraph)
195        */
196        RGraph.ClearEventListeners(this.id);
197
198
199        this.diameter    = Math.min(RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom, RGraph.GetWidth(this)) - this.gutterLeft - this.gutterRight;
200        this.radius      = this.Get('chart.radius') ? this.Get('chart.radius') : this.diameter / 2;
201        // this.centerx now defined below
202        this.centery     = ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
203        this.subTotal    = 0;
204        this.angles      = [];
205       
206        /**
207        * Alignment (Pie is center aligned by default) Only if centerx is not defined - donut defines the centerx
208        */
209        if (this.Get('chart.align') == 'left') {
210            this.centerx = this.radius + this.gutterLeft;
211       
212        } else if (this.Get('chart.align') == 'right') {
213            this.centerx = RGraph.GetWidth(this) - this.radius - this.gutterRight;
214       
215        } else {
216            this.centerx = RGraph.GetWidth(this) / 2;
217        }
218
219        /**
220        * Draw the shadow if required
221        */
222        if (this.Get('chart.shadow') && 0) {
223       
224            var offsetx = document.all ? this.Get('chart.shadow.offsetx') : 0;
225            var offsety = document.all ? this.Get('chart.shadow.offsety') : 0;
226
227            this.context.beginPath();
228            this.context.fillStyle = this.Get('chart.shadow.color');
229
230            this.context.shadowColor   = this.Get('chart.shadow.color');
231            this.context.shadowBlur    = this.Get('chart.shadow.blur');
232            this.context.shadowOffsetX = this.Get('chart.shadow.offsetx');
233            this.context.shadowOffsetY = this.Get('chart.shadow.offsety');
234           
235            this.context.arc(this.centerx + offsetx, this.centery + offsety, this.radius, 0, 6.28, 0);
236           
237            this.context.fill();
238           
239            // Now turn off the shadow
240            RGraph.NoShadow(this);
241        }
242
243        /**
244        * The total of the array of values
245        */
246        this.total = RGraph.array_sum(this.data);
247
248        for (var i=0,len=this.data.length; i<len; i++) {
249            var angle = (this.data[i] / this.total) * 360;
250   
251            // Draw the segment
252            this.DrawSegment(angle,this.Get('chart.colors')[i],i == (this.data.length - 1), i);
253        }
254
255        RGraph.NoShadow(this);
256
257
258        /**
259        * Redraw the seperating lines
260        */
261        this.DrawBorders();
262
263        /**
264        * Now draw the segments again with shadow turned off. This is always performed,
265        * not just if the shadow is on.
266        */
267        for (var i=0; i<this.angles.length; i++) {
268   
269            this.context.beginPath();
270                this.context.strokeStyle = this.Get('chart.strokestyle');
271                this.context.fillStyle = this.Get('chart.colors')[i];
272                this.context.moveTo(this.angles[i][2], this.angles[i][3]);
273                this.context.arc(this.angles[i][2], this.angles[i][3], this.radius, this.angles[i][0] / 57.3, this.angles[i][1] / 57.3, false);
274                this.context.lineTo(this.angles[i][2], this.angles[i][3]);
275            this.context.closePath();
276            this.context.fill();
277            this.context.stroke();
278        }
279
280        /**
281        * Draw label sticks
282        */
283        if (this.Get('chart.labels.sticks')) {
284            this.DrawSticks();
285           
286            // Redraw the border going around the Pie chart if the stroke style is NOT white
287            if (
288                  this.Get('chart.strokestyle') != 'white'
289               && this.Get('chart.strokestyle') != '#fff'
290               && this.Get('chart.strokestyle') != '#fffffff'
291               && this.Get('chart.strokestyle') != 'rgb(255,255,255)'
292               && this.Get('chart.strokestyle') != 'rgba(255,255,255,0)'
293              ) {
294
295               // Again (?)
296              this.DrawBorders();
297           }
298        }
299
300        /**
301        * Draw the labels
302        */
303        this.DrawLabels();
304
305        /**
306        * Draw the title
307        */
308        if (this.Get('chart.align') == 'left') {
309            var centerx = this.radius + this.Get('chart.gutter.left');
310
311        } else if (this.Get('chart.align') == 'right') {
312            var centerx = RGraph.GetWidth(this) - (this.radius + this.gutterRight);
313
314        } else {
315            var centerx = null;
316        }
317
318        RGraph.DrawTitle(this.canvas, this.Get('chart.title'), (this.canvas.height / 2) - this.radius - 5, centerx, this.Get('chart.text.size') + 2);
319       
320       
321        /**
322        * Setup the context menu if required
323        */
324        if (this.Get('chart.contextmenu')) {
325            RGraph.ShowContext(this);
326        }
327
328        /**
329        * Tooltips
330        */
331        if (this.Get('chart.tooltips').length) {
332
333            /**
334            * Register this object for redrawing
335            */
336            RGraph.Register(this);
337       
338            /**
339            * The onclick event
340            */
341            //this.canvas.onclick = function (e)
342            var canvas_onclick_func = function (e)
343            {
344                RGraph.HideZoomedCanvas();
345
346                e = RGraph.FixEventObject(e);
347
348                var mouseCoords = RGraph.getMouseXY(e);
349
350                var canvas  = e.target;
351                var context = canvas.getContext('2d');
352                var obj     = e.target.__object__;
353
354
355
356                /**
357                * If it's actually a donut make sure the hyp is bigger
358                * than the size of the hole in the middle
359                */
360                if (obj.Get('chart.variant') == 'donut' && Math.abs(hyp) < (obj.radius / 2)) {
361                    return;
362                }
363
364                /**
365                * The angles for each segment are stored in "angles",
366                * so go through that checking if the mouse position corresponds
367                */
368                var isDonut = obj.Get('chart.variant') == 'donut';
369                var hStyle  = obj.Get('chart.highlight.style');
370                var segment = obj.getSegment(e);
371
372                if (segment) {
373
374                    var x     = mouseCoords[0] - segment[0];
375                    var y     = mouseCoords[1] - segment[1];
376                    var theta = Math.atan(y / x); // RADIANS
377                    var hyp   = y / Math.sin(theta);
378
379
380                    if (RGraph.Registry.Get('chart.tooltip') && segment[5] == RGraph.Registry.Get('chart.tooltip').__index__) {
381                        return;
382                    } else {
383                        RGraph.Redraw();
384                    }
385
386
387                    if (isDonut || hStyle == '2d') {
388                       
389                        context.beginPath();
390
391                        context.strokeStyle = obj.Get('chart.highlight.style.2d.stroke');
392                        context.fillStyle   = obj.Get('chart.highlight.style.2d.fill');
393
394                        //context.moveTo(obj.centerx, obj.centery);
395
396                        context.moveTo(segment[0], segment[1]);
397                        context.arc(segment[0], segment[1], segment[2], RGraph.degrees2Radians(obj.angles[segment[5]][0]), RGraph.degrees2Radians(obj.angles[segment[5]][1]), 0);
398                        context.lineTo(segment[0], segment[1]);
399                        context.closePath();
400                       
401                        context.stroke();
402                        context.fill();
403                       
404                        //Removed 7th December 2010
405                        //context.stroke();
406
407                    } else if (hStyle == 'explode') {
408
409                        var exploded = [];
410
411                        exploded[segment[5]] = 0;
412
413                        RGraph.Registry.Set('chart.pie.exploded', obj);
414                       
415                        setTimeout(function () {var pie = RGraph.Registry.Get('chart.pie.exploded'); pie.Set('chart.exploded', exploded);RGraph.Clear(pie.canvas);pie.Draw(); exploded[segment[5]] += 7;}, 25);
416                        setTimeout(function () {var pie = RGraph.Registry.Get('chart.pie.exploded'); pie.Set('chart.exploded', exploded);RGraph.Clear(pie.canvas);pie.Draw(); exploded[segment[5]] += 7;}, 50);
417                        setTimeout(function () {var pie = RGraph.Registry.Get('chart.pie.exploded'); pie.Set('chart.exploded', exploded);RGraph.Clear(pie.canvas);pie.Draw(); exploded[segment[5]] += 7;}, 75);
418                        setTimeout(function () {var pie = RGraph.Registry.Get('chart.pie.exploded'); pie.Set('chart.exploded', exploded);RGraph.Clear(pie.canvas);pie.Draw(); exploded[segment[5]] += 7;}, 100);
419                        setTimeout(function () {var pie = RGraph.Registry.Get('chart.pie.exploded'); pie.Set('chart.exploded', exploded);RGraph.Clear(pie.canvas);pie.Draw(); exploded[segment[5]] += 7;}, 125);
420                       
421                        setTimeout(function () {RGraph.Registry.Get('chart.pie.exploded').Set('chart.exploded', []);}, 150);
422
423                    } else {
424
425                        context.lineWidth = 2;
426
427                        /**
428                        * Draw a white segment where the one that has been clicked on was
429                        */
430                        context.fillStyle = 'white';
431                        context.strokeStyle = 'white';
432                        context.beginPath();
433                        context.moveTo(segment[0], segment[1]);
434                        context.arc(segment[0], segment[1], segment[2], obj.angles[segment[5]][0] / 57.3, obj.angles[segment[5]][1] / 57.3, 0);
435                        context.stroke();
436                        context.fill();
437
438                        context.lineWidth = 1;
439
440                        context.shadowColor   = '#666';
441                        context.shadowBlur    = 3;
442                        context.shadowOffsetX = 3;
443                        context.shadowOffsetY = 3;
444
445                        // Draw the new segment
446                        context.beginPath();
447                            context.fillStyle   = obj.Get('chart.colors')[segment[5]];
448                            context.strokeStyle = obj.Get('chart.strokestyle');
449                            context.moveTo(segment[0] - 3, segment[1] - 3);
450                            context.arc(segment[0] - 3, segment[1] - 3, segment[2], RGraph.degrees2Radians(obj.angles[segment[5]][0]), RGraph.degrees2Radians(obj.angles[segment[5]][1]), 0);
451                            context.lineTo(segment[0] - 3, segment[1] - 3);
452                        context.closePath();
453                       
454                        context.stroke();
455                        context.fill();
456                       
457                        // Turn off the shadow
458                        RGraph.NoShadow(obj);
459                       
460                        /**
461                        * If a border is defined, redraw that
462                        */
463                        if (obj.Get('chart.border')) {
464                            context.beginPath();
465                            context.strokeStyle = obj.Get('chart.border.color');
466                            context.lineWidth = 5;
467                            context.arc(segment[0] - 3, segment[1] - 3, obj.radius - 2, RGraph.degrees2Radians(obj.angles[i][0]), RGraph.degrees2Radians(obj.angles[i][1]), 0);
468                            context.stroke();
469                        }
470                    }
471                       
472                    /**
473                    * If a tooltip is defined, show it
474                    */
475
476                    /**
477                    * Get the tooltip text
478                    */
479                    if (typeof(obj.Get('chart.tooltips')) == 'function') {
480                        var text = String(obj.Get('chart.tooltips')(segment[5]));
481
482                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[segment[5]]) == 'function') {
483                        var text = String(obj.Get('chart.tooltips')[segment[5]](segment[5]));
484                   
485                    } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
486                        var text = String(obj.Get('chart.tooltips')[segment[5]]);
487
488                    } else {
489                        var text = '';
490                    }
491
492                    if (text) {
493                        RGraph.Tooltip(canvas, text, e.pageX, e.pageY, segment[5]);
494                    }
495
496                    /**
497                    * Need to redraw the key?
498                    */
499                    if (obj.Get('chart.key') && obj.Get('chart.key').length && obj.Get('chart.key.position') == 'graph') {
500                        RGraph.DrawKey(obj, obj.Get('chart.key'), obj.Get('chart.colors'));
501                    }
502
503                    e.stopPropagation();
504
505                    return;
506                } else if (obj.Get('chart.tooltips.event') == 'onclick') {
507                    RGraph.Redraw();
508                }
509            }
510            var event_name = this.Get('chart.tooltips.event') == 'onmousemove' ? 'mousemove' : 'click';
511
512            this.canvas.addEventListener(event_name, canvas_onclick_func, false);
513            RGraph.AddEventListener(this.id, event_name, canvas_onclick_func);
514
515
516
517
518
519
520            /**
521            * The onmousemove event for changing the cursor
522            */
523            //this.canvas.onmousemove = function (e)
524            var canvas_onmousemove_func = function (e)
525            {
526                RGraph.HideZoomedCanvas();
527
528                e = RGraph.FixEventObject(e);
529               
530                var obj     = e.target.__object__;
531                var segment = obj.getSegment(e);
532
533                if (segment) {
534                    e.target.style.cursor = 'pointer';
535
536                    return;
537                }
538
539                /**
540                * Put the cursor back to null
541                */
542                e.target.style.cursor = 'default';
543            }
544            this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
545            RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
546
547
548
549
550
551
552
553
554
555            /**
556            * The window onclick function
557            */
558            var window_onclick_func = function (e)
559            {
560                RGraph.HideZoomedCanvas();
561
562                e = RGraph.FixEventObject(e);
563
564                RGraph.Redraw();
565
566                /**
567                * Put the cursor back to null
568                */
569                e.target.style.cursor = 'default';
570            }
571            window.addEventListener('click', window_onclick_func, false);
572            RGraph.AddEventListener('window_' + this.id, 'click', window_onclick_func);
573        }
574
575
576        /**
577        * If a border is pecified, draw it
578        */
579        if (this.Get('chart.border')) {
580            this.context.beginPath();
581            this.context.lineWidth = 5;
582            this.context.strokeStyle = this.Get('chart.border.color');
583
584            this.context.arc(this.centerx,
585                             this.centery,
586                             this.radius - 2,
587                             0,
588                             6.28,
589                             0);
590
591            this.context.stroke();
592        }
593       
594        /**
595        * Draw the kay if desired
596        */
597        if (this.Get('chart.key') != null) {
598            //this.Set('chart.key.position', 'graph');
599            RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors'));
600        }
601
602
603        /**
604        * If this is actually a donut, draw a big circle in the middle
605        */
606        if (this.Get('chart.variant') == 'donut') {
607            this.context.beginPath();
608            this.context.strokeStyle = this.Get('chart.strokestyle');
609            this.context.fillStyle   = this.Get('chart.variant.donut.color');
610            this.context.arc(this.centerx, this.centery, this.radius / 2, 0, 6.28, 0);
611            this.context.stroke();
612            this.context.fill();
613        }
614       
615        RGraph.NoShadow(this);
616       
617        /**
618        * If the canvas is annotatable, do install the event handlers
619        */
620        if (this.Get('chart.annotatable')) {
621            RGraph.Annotate(this);
622        }
623       
624        /**
625        * This bit shows the mini zoom window if requested
626        */
627        if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
628            RGraph.ShowZoomWindow(this);
629        }
630
631       
632        /**
633        * This function enables resizing
634        */
635        if (this.Get('chart.resizable')) {
636            RGraph.AllowResizing(this);
637        }
638       
639        /**
640        * Fire the RGraph ondraw event
641        */
642        RGraph.FireCustomEvent(this, 'ondraw');
643    }
644
645
646    /**
647    * Draws a single segment of the pie chart
648    *
649    * @param int degrees The number of degrees for this segment
650    */
651    RGraph.Pie.prototype.DrawSegment = function (degrees, color, last, index)
652    {
653        var context  = this.context;
654        var canvas   = this.canvas;
655        var subTotal = this.subTotal;
656
657        context.beginPath();
658
659            context.fillStyle   = color;
660            context.strokeStyle = this.Get('chart.strokestyle');
661            context.lineWidth   = 0;
662           
663            if (this.Get('chart.shadow')) {
664                RGraph.SetShadow(this, this.Get('chart.shadow.color'),this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur'));
665            }
666
667            /**
668            * Exploded segments
669            */
670            if ( (typeof(this.Get('chart.exploded')) == 'object' && this.Get('chart.exploded')[index] > 0)) {
671                var explosion = this.Get('chart.exploded')[index];
672                var x         = 0;
673                var y         = 0;
674                var h         = explosion;
675                var t         = (subTotal + (degrees / 2)) / (360/6.2830);
676                var x         = (Math.cos(t) * explosion);
677                var y         = (Math.sin(t) * explosion);
678           
679                this.context.moveTo(this.centerx + x, this.centery + y);
680            } else {
681                var x = 0;
682                var y = 0;
683            }
684
685            context.arc(this.centerx + x,
686                        this.centery + y,
687                        this.radius,
688                        subTotal / 57.3,
689                        (last ? 360 : subTotal + degrees) / 57.3,
690                        0);
691   
692            context.lineTo(this.centerx + x, this.centery + y);
693           
694            // Keep hold of the angles
695            this.angles.push([subTotal, subTotal + degrees, this.centerx + x, this.centery + y])
696        this.context.closePath();
697       
698
699       
700        //this.context.stroke();
701        this.context.fill();
702
703        /**
704        * Calculate the segment angle
705        */
706        this.Get('chart.segments').push([subTotal, subTotal + degrees]);
707        this.subTotal += degrees;
708    }
709
710    /**
711    * Draws the graphs labels
712    */
713    RGraph.Pie.prototype.DrawLabels = function ()
714    {
715        var hAlignment = 'left';
716        var vAlignment = 'center';
717        var labels     = this.Get('chart.labels');
718        var context    = this.context;
719
720        /**
721        * Turn the shadow off
722        */
723        RGraph.NoShadow(this);
724       
725        context.fillStyle = 'black';
726        context.beginPath();
727
728        /**
729        * Draw the key (ie. the labels)
730        */
731        if (labels && labels.length) {
732
733            var text_size = this.Get('chart.text.size');
734
735            for (i=0; i<labels.length; ++i) {
736           
737                /**
738                * T|his ensures that if we're given too many labels, that we don't get an error
739                */
740                if (typeof(this.Get('chart.segments')[i]) == 'undefined') {
741                    continue;
742                }
743
744                // Move to the centre
745                context.moveTo(this.centerx,this.centery);
746               
747                var a = this.Get('chart.segments')[i][0] + ((this.Get('chart.segments')[i][1] - this.Get('chart.segments')[i][0]) / 2);
748
749                /**
750                * Alignment
751                */
752                if (a < 90) {
753                    hAlignment = 'left';
754                    vAlignment = 'center';
755                } else if (a < 180) {
756                    hAlignment = 'right';
757                    vAlignment = 'center';
758                } else if (a < 270) {
759                    hAlignment = 'right';
760                    vAlignment = 'center';
761                } else if (a < 360) {
762                    hAlignment = 'left';
763                    vAlignment = 'center';
764                }
765
766
767                /**
768                * Handle the additional "explosion" offset
769                */
770                if (typeof(this.Get('chart.exploded')) == 'object' && this.Get('chart.exploded')[i]) {
771
772                    var t = ((this.angles[i][1] - this.angles[i][0]) / 2) / (360/6.2830);
773                    var seperation = this.Get('chart.exploded')[i];
774                    var angle = ((this.angles[i][1] - this.angles[i][0]) / 2) + this.angles[i][0];
775
776                    // Adjust the angles
777                    var explosion_offsetx = (Math.cos(angle / 57.29) * seperation);
778                    var explosion_offsety = (Math.sin(angle / 57.29) * seperation);
779                } else {
780                    var explosion_offsetx = 0;
781                    var explosion_offsety = 0;
782                }
783
784                context.fillStyle = this.Get('chart.text.color');
785
786                RGraph.Text(context,
787                            this.Get('chart.text.font'),
788                            text_size,
789                            this.centerx + explosion_offsetx + ((this.radius + 10)* Math.cos(a / 57.3)) + (this.Get('chart.labels.sticks') ? (a < 90 || a > 270 ? 2 : -2) : 0),
790                            this.centery + explosion_offsety + (((this.radius + 10) * Math.sin(a / 57.3))),
791                            labels[i],
792                            vAlignment,
793                            hAlignment);
794            }
795           
796            context.fill();
797        }
798    }
799
800
801    /**
802    * This function draws the pie chart sticks (for the labels)
803    */
804    RGraph.Pie.prototype.DrawSticks = function ()
805    {
806        var context  = this.context;
807        var segments = this.Get('chart.segments');
808        var offset   = this.Get('chart.linewidth') / 2;
809        var exploded = this.Get('chart.exploded');
810        var sticks   = this.Get('chart.labels.sticks');
811
812        for (var i=0; i<segments.length; ++i) {
813       
814            // This allows the chart.labels.sticks to be an array as well as a boolean
815            if (typeof(sticks) == 'object' && !sticks[i]) {
816                continue;
817            }
818
819            var degrees = segments[i][1] - segments[i][0];
820
821            context.beginPath();
822            context.strokeStyle = this.Get('chart.labels.sticks.color');
823            context.lineWidth   = 1;
824
825            var midpoint = (segments[i][0] + (degrees / 2)) / 57.3;
826
827            if (exploded && exploded[i]) {
828                var extra = exploded[i];
829            } else {
830                var extra = 0;
831            }
832           
833            context.lineJoin = 'round';
834            context.lineWidth = 1;
835
836            context.arc(this.centerx,
837                        this.centery,
838                        this.radius + 7 + extra,
839                        midpoint,
840                        midpoint + 0.01,
841                        0);
842           
843            context.arc(this.centerx,
844                        this.centery,
845                        this.radius - offset + extra,
846                        midpoint,
847                        midpoint + 0.01,
848                        0);
849
850            context.stroke();
851        }
852    }
853
854
855    /**
856    * The (now Pie chart specific) getSegment function
857    *
858    * @param object e The event object
859    */
860    RGraph.Pie.prototype.getSegment = function (e)
861    {
862        RGraph.FixEventObject(e);
863
864        // The optional arg provides a way of allowing some accuracy (pixels)
865        var accuracy = arguments[1] ? arguments[1] : 0;
866
867        var obj         = e.target.__object__;
868        var canvas      = obj.canvas;
869        var context     = obj.context;
870        var mouseCoords = RGraph.getMouseXY(e);
871        var r           = obj.radius;
872        var angles      = obj.angles;
873        var ret         = [];
874
875        for (var i=0; i<angles.length; ++i) {
876
877            var x     = mouseCoords[0] - angles[i][2];
878            var y     = mouseCoords[1] - angles[i][3];
879            var theta = Math.atan(y / x); // RADIANS
880            var hyp   = y / Math.sin(theta);
881            var hyp   = (hyp < 0) ? hyp + accuracy : hyp - accuracy;
882            // Put theta in DEGREES
883            theta *= 57.3
884
885            /**
886            * Account for the correct quadrant
887            */
888            if (x < 0 && y >= 0) {
889                theta += 180;
890            } else if (x < 0 && y < 0) {
891                theta += 180;
892            } else if (x > 0 && y < 0) {
893                theta += 360;
894            }
895           
896            if (theta > 360) {
897                theta -= 360;
898            }
899
900            if (theta >= angles[i][0] && theta < angles[i][1]) {
901
902                hyp = Math.abs(hyp);
903
904                if (!hyp || (obj.radius && hyp > obj.radius) ) {
905                    return null;
906                }
907
908                if (obj.type == 'pie' && obj.Get('chart.variant') == 'donut' && (hyp > obj.radius || hyp < (obj.radius / 2) ) ) {
909                    return null;
910                }
911
912                ret[0] = angles[i][2];
913                ret[1] = angles[i][3];
914                ret[2] = (obj.type == 'rose') ? angles[i][2] : obj.radius;
915                ret[3] = angles[i][0];
916                ret[4] = angles[i][1];
917                ret[5] = i;
918
919
920               
921                if (ret[3] < 0) ret[3] += 360;
922                if (ret[4] > 360) ret[4] -= 360;
923
924                return ret;
925            }
926        }
927       
928        return null;
929    }
930
931
932    RGraph.Pie.prototype.DrawBorders = function ()
933    {
934        if (this.Get('chart.linewidth') > 0) {
935
936            this.context.lineWidth = this.Get('chart.linewidth');
937            this.context.strokeStyle = this.Get('chart.strokestyle');
938
939            for (var i=0,len=this.angles.length; i<len; ++i) {
940                this.context.beginPath();
941                    this.context.moveTo(this.angles[i][2], this.angles[i][3]);
942                    this.context.arc(this.angles[i][2], this.angles[i][3], this.radius, this.angles[i][0] / 57.3, (this.angles[i][0] + 0.01) / 57.3, 0);
943                    this.context.arc(this.angles[i][2], this.angles[i][3], this.radius, this.angles[i][0] / 57.3, (this.angles[i][1]) / 57.3, 0);
944                this.context.closePath();
945               
946                this.context.stroke();
947            }
948        }
949    }
Note: See TracBrowser for help on using the repository browser.