source: Dev/branches/jQueryUI/client/RGraph/libraries/RGraph.rose.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: 37.1 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 rose chart constuctor
19    *
20    * @param object canvas
21    * @param array data
22    */
23    RGraph.Rose = function (id, data)
24    {
25        this.id                = id;
26        this.canvas            = document.getElementById(id);
27        this.context           = this.canvas.getContext('2d');
28        this.data              = data;
29        this.canvas.__object__ = this;
30        this.type              = 'rose';
31        this.isRGraph          = true;
32
33
34        /**
35        * Compatibility with older browsers
36        */
37        RGraph.OldBrowserCompat(this.context);
38
39
40        this.centerx = 0;
41        this.centery = 0;
42        this.radius  = 0;
43        this.max     = 0;
44       
45        this.properties = {
46            'chart.radius':                 null,
47            'chart.colors':                 ['red', 'rgb(0,255,255)', 'rgb(0,255,0)', 'gray', 'blue', 'rgb(255,128,255)','green', 'pink', 'gray', 'aqua'],
48            'chart.colors.sequential':      false,
49            'chart.colors.alpha':           null,
50            'chart.strokestyle':            'rgba(0,0,0,0.5)',
51            'chart.gutter.left':            25,
52            'chart.gutter.right':           25,
53            'chart.gutter.top':             25,
54            'chart.gutter.bottom':          25,
55            'chart.title':                  '',
56            'chart.title.background':       null,
57            'chart.title.hpos':             null,
58            'chart.title.vpos':             null,
59            'chart.labels':                 null,
60            'chart.labels.position':       'center',
61            'chart.labels.axes':            'nsew',
62            'chart.labels.offset':          0,
63            'chart.text.color':             'black',
64            'chart.text.font':              'Verdana',
65            'chart.text.size':              10,
66            'chart.key':                    null,
67            'chart.key.background':         'white',
68            'chart.key.position':           'graph',
69            'chart.key.halign':             'right',
70            'chart.key.shadow':             false,
71            'chart.key.shadow.color':       '#666',
72            'chart.key.shadow.blur':        3,
73            'chart.key.shadow.offsetx':     2,
74            'chart.key.shadow.offsety':     2,
75            'chart.key.position.gutter.boxed': true,
76            'chart.key.position.x':         null,
77            'chart.key.position.y':         null,
78            'chart.key.color.shape':        'square',
79            'chart.key.rounded':            true,
80            'chart.key.linewidth':          1,
81            'chart.contextmenu':            null,
82            'chart.tooltips':               null,
83            'chart.tooltips.event':         'onclick',
84            'chart.tooltips.effect':        'fade',
85            'chart.tooltips.css.class':     'RGraph_tooltip',
86            'chart.tooltips.highlight':     true,
87            'chart.highlight.stroke':       'black',
88            'chart.highlight.fill':         'rgba(255,255,255,0.5)',
89            'chart.annotatable':            false,
90            'chart.annotate.color':         'black',
91            'chart.zoom.factor':            1.5,
92            'chart.zoom.fade.in':           true,
93            'chart.zoom.fade.out':          true,
94            'chart.zoom.hdir':              'right',
95            'chart.zoom.vdir':              'down',
96            'chart.zoom.frames':            10,
97            'chart.zoom.delay':             50,
98            'chart.zoom.shadow':            true,
99            'chart.zoom.mode':              'canvas',
100            'chart.zoom.thumbnail.width':   75,
101            'chart.zoom.thumbnail.height':  75,
102            'chart.zoom.background':        true,
103            'chart.zoom.action':            'zoom',
104            'chart.resizable':              false,
105            'chart.resize.handle.adjust':   [0,0],
106            'chart.resize.handle.background': null,
107            'chart.adjustable':             false,
108            'chart.ymax':                   null,
109            'chart.ymin':                   0,
110            'chart.scale.decimals':         null,
111            'chart.variant':                'stacked'
112        }
113
114
115        /**
116        * Set the .getShape commonly named method
117        */
118        this.getShape = this.getSegment;
119    }
120
121
122    /**
123    * A simple setter
124    *
125    * @param string name  The name of the property to set
126    * @param string value The value of the property
127    */
128    RGraph.Rose.prototype.Set = function (name, value)
129    {
130        this.properties[name.toLowerCase()] = value;
131    }
132   
133   
134    /**
135    * A simple getter
136    *
137    * @param string name The name of the property to get
138    */
139    RGraph.Rose.prototype.Get = function (name)
140    {
141        return this.properties[name.toLowerCase()];
142    }
143
144   
145    /**
146    * This method draws the rose chart
147    */
148    RGraph.Rose.prototype.Draw = function ()
149    {
150        /**
151        * Fire the onbeforedraw event
152        */
153        RGraph.FireCustomEvent(this, 'onbeforedraw');
154       
155        /**
156        * Clear all of this canvases event handlers (the ones installed by RGraph)
157        */
158        RGraph.ClearEventListeners(this.id);
159
160       
161        /**
162        * This doesn't affect the chart, but is used for compatibility
163        */
164        this.gutterLeft   = this.Get('chart.gutter.left');
165        this.gutterRight  = this.Get('chart.gutter.right');
166        this.gutterTop    = this.Get('chart.gutter.top');
167        this.gutterBottom = this.Get('chart.gutter.bottom');
168
169        // Calculate the radius
170        this.radius       = (Math.min(RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight, RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2);
171        this.centerx      = RGraph.GetWidth(this) / 2;
172        this.centery      = RGraph.GetHeight(this) / 2;
173        this.angles       = [];
174        this.total        = 0;
175        this.startRadians = 0;
176       
177        // User specified radius
178        if (typeof(this.Get('chart.radius')) == 'number') {
179            this.radius = this.Get('chart.radius');
180        }
181       
182        /**
183        * Change the centerx marginally if the key is defined
184        */
185        if (this.Get('chart.key') && this.Get('chart.key').length > 0 && this.Get('chart.key').length >= 3) {
186            this.centerx = this.centerx - this.Get('chart.gutter.right') + 5;
187        }
188
189        this.DrawBackground();
190        this.DrawRose();
191        this.DrawLabels();
192
193        /**
194        * Setup the context menu if required
195        */
196        if (this.Get('chart.contextmenu')) {
197            RGraph.ShowContext(this);
198        }
199
200        /**
201        * Tooltips
202        */
203        if (this.Get('chart.tooltips')) {
204
205            /**
206            * Register this object for redrawing
207            */
208            RGraph.Register(this);
209       
210            /**
211            * The onclick event
212            */
213            var canvas_onclick_func = function (e)
214            {
215                var obj     = e.target.__object__;
216                var canvas  = e.target;
217                var context = canvas.getContext('2d');
218
219                e = RGraph.FixEventObject(e);
220
221                RGraph.Redraw();
222               
223                var segment = obj.getSegment(e);
224
225                if (segment && obj.Get('chart.tooltips')) {
226
227                    /**
228                    * Get the tooltip text
229                    */
230                    if (typeof(obj.Get('chart.tooltips')) == 'function') {
231                        var text = String(obj.Get('chart.tooltips')(segment[6]));
232                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[segment[6]]) == 'function') {
233                        var text = String(obj.Get('chart.tooltips')[segment[6]](segment[6]));
234                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[segment[6]]) == 'string' || typeof(obj.Get('chart.tooltips')[segment[6]]) == 'number')) {
235                        var text = String(obj.Get('chart.tooltips')[segment[6]]);
236                    } else {
237                        var text = null;
238                    }
239
240                    if (text) {
241                        context.beginPath();
242                            context.strokeStyle = obj.Get('chart.highlight.stroke');
243                            context.fillStyle   = obj.Get('chart.highlight.fill');
244                           
245                            // This highlights the chart
246                            context.arc(obj.centerx, obj.centery, segment[3], segment[4] / 57.3, segment[5] / 57.3, false);
247                            context.arc(obj.centerx, obj.centery, segment[2] + 0.01, segment[5] / 57.3, segment[4] / 57.3, true);
248   
249                        context.closePath();
250   
251                        context.fill();
252                        context.stroke();
253   
254                        context.strokeStyle = 'rgba(0,0,0,0)';
255
256                        // Taken out on 12th June 2011
257                        //obj.DrawLabels();
258                       
259                        /**
260                        * Show the tooltip
261                        */
262                        RGraph.Tooltip(canvas, text, e.pageX, e.pageY, segment[6]);
263   
264                        e.stopPropagation();
265                    }
266
267                    return;
268                }
269            }
270            this.canvas.addEventListener('click', canvas_onclick_func, false);
271            RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
272
273
274            /**
275            * The onmousemove event
276            */
277            var canvas_onmousemove_func = function (e)
278            {
279
280                var obj     = e.target.__object__;
281                var canvas  = e.target;
282                var context = canvas.getContext('2d');
283
284                e = RGraph.FixEventObject(e);
285
286                var segment = obj.getSegment(e);
287
288                if (segment && obj.Get('chart.tooltips')) {
289
290                    /**
291                    * Get the tooltip text
292                    */
293                    if (typeof(obj.Get('chart.tooltips')) == 'function') {
294                        var text = String(obj.Get('chart.tooltips')(segment[6]));
295                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[segment[6]]) == 'function') {
296                        var text = String(obj.Get('chart.tooltips')[segment[6]](segment[6]));
297                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[segment[6]]) == 'string' || typeof(obj.Get('chart.tooltips')[segment[6]]) == 'number')) {
298                        var text = String(obj.Get('chart.tooltips')[segment[6]]);
299                    } else {
300                        var text = null;
301                    }
302
303                    if (text) {
304                        canvas.style.cursor = 'pointer';
305               
306                        /*******************************************************
307                        * This is here in case tooltips are using the
308                        * onmousemove event
309                        *******************************************************/
310                        if (obj.Get('chart.tooltips.event') == 'onmousemove') {
311                            if (!RGraph.Registry.Get('chart.tooltip') || RGraph.Registry.Get('chart.tooltip').__index__ != segment[6]) {
312                                canvas_onclick_func(e);
313                            }
314                        }
315
316                    } else {
317                        canvas.style.cursor = 'default';
318                    }
319
320                    return;
321                }
322
323                canvas.style.cursor = 'default';
324            }
325            this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
326            RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
327        }
328       
329        /**
330        * If the canvas is annotatable, do install the event handlers
331        */
332        if (this.Get('chart.annotatable')) {
333            RGraph.Annotate(this);
334        }
335       
336        /**
337        * This bit shows the mini zoom window if requested
338        */
339        if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
340            RGraph.ShowZoomWindow(this);
341        }
342
343       
344        /**
345        * This function enables resizing
346        */
347        if (this.Get('chart.resizable')) {
348            RGraph.AllowResizing(this);
349        }
350
351       
352        /**
353        * This function enables adjusting
354        */
355        if (this.Get('chart.adjustable')) {
356            RGraph.AllowAdjusting(this);
357        }
358       
359        /**
360        * Fire the RGraph ondraw event
361        */
362        RGraph.FireCustomEvent(this, 'ondraw');
363    }
364
365    /**
366    * This method draws the rose charts background
367    */
368    RGraph.Rose.prototype.DrawBackground = function ()
369    {
370        this.context.lineWidth = 1;
371   
372        // Draw the background grey circles
373        this.context.strokeStyle = '#ccc';
374        for (var i=15; i<this.radius - (RGraph.isIE8() ? 5 : 0); i+=15) {// Radius must be greater than 0 for Opera to work
375            //this.context.moveTo(this.centerx + i, this.centery);
376   
377            // Radius must be greater than 0 for Opera to work
378            this.context.arc(this.centerx, this.centery, i, 0, (2 * Math.PI), 0);
379        }
380        this.context.stroke();
381
382        // Draw the background lines that go from the center outwards
383        this.context.beginPath();
384        for (var i=15; i<360; i+=15) {
385       
386            // Radius must be greater than 0 for Opera to work
387            this.context.arc(this.centerx, this.centery, this.radius, i / 57.3, (i + 0.1) / 57.3, 0); // The 0.1 avoids a bug in Chrome 6
388       
389            this.context.lineTo(this.centerx, this.centery);
390        }
391        this.context.stroke();
392       
393        this.context.beginPath();
394        this.context.strokeStyle = 'black';
395   
396        // Draw the X axis
397        this.context.moveTo(this.centerx - this.radius, this.centery);
398        this.context.lineTo(this.centerx + this.radius, this.centery);
399   
400        // Draw the X ends
401        this.context.moveTo(this.centerx - this.radius, this.centery - 5);
402        this.context.lineTo(this.centerx - this.radius, this.centery + 5);
403        this.context.moveTo(this.centerx + this.radius, this.centery - 5);
404        this.context.lineTo(this.centerx + this.radius, this.centery + 5);
405       
406        // Draw the X check marks
407        for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=20) {
408            this.context.moveTo(i,  this.centery - 3);
409            this.context.lineTo(i,  this.centery + 3);
410        }
411       
412        // Draw the Y check marks
413        for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=20) {
414            this.context.moveTo(this.centerx - 3, i);
415            this.context.lineTo(this.centerx + 3, i);
416        }
417   
418        // Draw the Y axis
419        this.context.moveTo(this.centerx, this.centery - this.radius);
420        this.context.lineTo(this.centerx, this.centery + this.radius);
421   
422        // Draw the Y ends
423        this.context.moveTo(this.centerx - 5, this.centery - this.radius);
424        this.context.lineTo(this.centerx + 5, this.centery - this.radius);
425   
426        this.context.moveTo(this.centerx - 5, this.centery + this.radius);
427        this.context.lineTo(this.centerx + 5, this.centery + this.radius);
428       
429        // Stroke it
430        this.context.closePath();
431        this.context.stroke();
432    }
433
434
435    /**
436    * This method draws the data on the graph
437    */
438    RGraph.Rose.prototype.DrawRose = function ()
439    {
440        var max  = 0;
441        var data = this.data;
442
443        // Must be at least two data points
444        if (data.length < 2) {
445            alert('[ROSE] Must be at least two data points! [' + data + ']');
446            return;
447        }
448   
449        // Work out the maximum value and the sum
450        if (!this.Get('chart.ymax')) {
451            // Work out the max
452            for (var i=0; i<data.length; ++i) {
453                if (typeof(data[i]) == 'number') {
454                    max = Math.max(max, data[i]);
455                } else if (typeof(data[i]) == 'object' && this.Get('chart.variant') == 'non-equi-angular') {
456                    max = Math.max(max, data[i][0]);
457               
458                // Fallback is stacked
459                } else {
460                    max = Math.max(max, RGraph.array_sum(data[i]));
461                }
462            }
463
464            this.scale = RGraph.getScale(max, this);
465            this.max = this.scale[4];
466        } else {
467            var ymax = this.Get('chart.ymax');
468            var ymin = this.Get('chart.ymin');
469
470            this.scale = [
471                          ((ymax - ymin) * 0.2) + ymin,
472                          ((ymax - ymin) * 0.4) + ymin,
473                          ((ymax - ymin) * 0.6) + ymin,
474                          ((ymax - ymin) * 0.8) + ymin,
475                          ((ymax - ymin) * 1.0) + ymin
476                         ];
477            this.max = this.scale[4];
478        }
479       
480        this.sum = RGraph.array_sum(data);
481       
482        // Move to the centre
483        this.context.moveTo(this.centerx, this.centery);
484   
485        this.context.stroke(); // Stroke the background so it stays grey
486   
487        // Transparency
488        if (this.Get('chart.colors.alpha')) {
489            this.context.globalAlpha = this.Get('chart.colors.alpha');
490        }
491
492        /*******************************************************
493        * A non-equi-angular Rose chart
494        *******************************************************/
495        if (typeof(this.Get('chart.variant')) == 'string' && this.Get('chart.variant') == 'non-equi-angular') {
496            /*******************************************************
497            * NON-EQUI-ANGULAR GOES HERE
498            *******************************************************/
499            var total=0;
500            for (var i=0; i<data.length; ++i) {
501                total += data[i][1];
502            }
503           
504           
505            for (var i=0; i<this.data.length; ++i) {
506           
507                var segmentRadians = (this.data[i][1] / total) * (2 * Math.PI);
508                var radius         = ((this.data[i][0] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
509               
510                this.context.strokeStyle = this.Get('chart.strokestyle');
511                this.context.fillStyle = this.Get('chart.colors')[0];
512               
513                if (this.Get('chart.colors.sequential')) {
514                    this.context.fillStyle = this.Get('chart.colors')[i];
515                }
516           
517                this.context.beginPath(); // Begin the segment
518                    this.context.arc(this.centerx, this.centery, radius, this.startRadians - (Math.PI / 2), this.startRadians + segmentRadians - (Math.PI / 2), 0);
519                    this.context.lineTo(this.centerx, this.centery);
520                this.context.closePath(); // End the segment
521               
522                this.context.stroke();
523                this.context.fill();
524               
525                // Store the start and end angles
526                this.angles.push([
527                                  ((this.startRadians - (Math.PI / 2)) * 57.3) + 90,
528                                  (((this.startRadians + segmentRadians) - (Math.PI / 2)) * 57.3) + 90,
529                                  0,
530                                  radius
531                                 ]);
532
533                this.startRadians += segmentRadians;
534            }
535        } else {
536            /*******************************************************
537            * Draw the segments
538            *******************************************************/
539            for (var i=0; i<this.data.length; ++i) {
540   
541                this.context.strokeStyle = this.Get('chart.strokestyle');
542                this.context.fillStyle = this.Get('chart.colors')[0];
543               
544                /*******************************************************
545                * This allows sequential colors
546                *******************************************************/
547                if (this.Get('chart.colors.sequential')) {
548                    this.context.fillStyle = this.Get('chart.colors')[i];
549                }
550       
551                var segmentRadians = (1 / this.data.length) * (2 * Math.PI);
552   
553                if (typeof(this.data[i]) == 'number') {
554                    this.context.beginPath(); // Begin the segment
555                        var radius = ((this.data[i] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
556       
557                        this.context.arc(this.centerx, this.centery, radius, this.startRadians - (Math.PI / 2), this.startRadians + segmentRadians - (Math.PI / 2), 0);
558                        this.context.lineTo(this.centerx, this.centery);
559                    this.context.closePath(); // End the segment
560                    this.context.stroke();
561                    this.context.fill();
562                   
563                    // Store the start and end angles
564                    this.angles.push([
565                                      ((this.startRadians - (Math.PI / 2)) * 57.3) + 90,
566                                      (((this.startRadians + segmentRadians) - (Math.PI / 2)) * 57.3) + 90,
567                                      0,
568                                      radius
569                                     ]);
570                /*******************************************************
571                * Draw a stacked segment
572                *******************************************************/
573                } else if (typeof(this.data[i]) == 'object') {
574
575                    for (var j=0; j<this.data[i].length; ++j) {
576   
577                        this.context.fillStyle = this.Get('chart.colors')[j];
578                        if (j == 0) {
579                            this.context.beginPath(); // Begin the segment
580                                var startRadius = 0;
581                                var endRadius = ((this.data[i][j] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
582                   
583                                this.context.arc(this.centerx,
584                                                 this.centery,
585                                                 endRadius,
586                                                 this.startRadians - (Math.PI / 2),
587                                                 this.startRadians + segmentRadians - (Math.PI / 2),
588                                                 0);
589                                this.context.lineTo(this.centerx, this.centery);
590                            this.context.closePath(); // End the segment
591                            this.context.stroke();
592                            this.context.fill();
593   
594                            this.angles.push([
595                                              ((this.startRadians - (Math.PI / 2)) * 57.3) + 90,
596                                              (((this.startRadians + segmentRadians) - (Math.PI / 2)) * 57.3) + 90,
597                                              0,
598                                              endRadius
599                                             ]);
600                       
601                        } else {
602               
603                            this.context.beginPath(); // Begin the segment
604                                var startRadius = endRadius; // This comes from the prior iteration of this loop
605                                var endRadius = (((this.data[i][j] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10)) + startRadius;
606               
607                                this.context.arc(this.centerx,
608                                                 this.centery,
609                                                 startRadius,
610                                                 this.startRadians - (Math.PI / 2),
611                                                 this.startRadians + segmentRadians - (Math.PI / 2),
612                                                 0);
613               
614                                this.context.arc(this.centerx,
615                                                 this.centery,
616                                                 endRadius,
617                                                 this.startRadians + segmentRadians - (Math.PI / 2),
618                                                 this.startRadians - (Math.PI / 2),
619                                                 true);
620               
621                            this.context.closePath(); // End the segment
622                            this.context.stroke();
623                            this.context.fill();
624   
625                            this.angles.push([
626                                              ((this.startRadians - (Math.PI / 2)) * 57.3) + 90,
627                                              ((this.startRadians + segmentRadians - (Math.PI / 2)) * 57.3) + 90,
628                                              startRadius,
629                                              endRadius
630                                             ]);
631                        }
632                    }
633                }
634   
635                this.startRadians += segmentRadians;
636            }
637        }
638
639        // Turn off the transparency
640        if (this.Get('chart.colors.alpha')) {
641            this.context.globalAlpha = 1;
642        }
643
644        // Draw the title if any has been set
645        if (this.Get('chart.title')) {
646            RGraph.DrawTitle(this.canvas,
647                             this.Get('chart.title'),
648                             (this.canvas.height / 2) - this.radius,
649                             this.centerx,
650                             this.Get('chart.text.size') + 2);
651        }
652    }
653
654
655    /**
656    * Unsuprisingly, draws the labels
657    */
658    RGraph.Rose.prototype.DrawLabels = function ()
659    {
660        this.context.lineWidth = 1;
661        var key = this.Get('chart.key');
662
663        if (key && key.length) {
664            RGraph.DrawKey(this, key, this.Get('chart.colors'));
665        }
666       
667        // Set the color to black
668        this.context.fillStyle = 'black';
669        this.context.strokeStyle = 'black';
670       
671        var r         = this.radius - 10;
672        var font_face = this.Get('chart.text.font');
673        var font_size = this.Get('chart.text.size');
674        var context   = this.context;
675        var axes      = this.Get('chart.labels.axes').toLowerCase();
676
677        // Draw any labels
678
679        if (typeof(this.Get('chart.labels')) == 'object' && this.Get('chart.labels')) {
680            this.DrawCircularLabels(context, this.Get('chart.labels'), font_face, font_size, r + 10);
681        }
682
683
684        var color = 'rgba(255,255,255,0.8)';
685
686        // The "North" axis labels
687        if (axes.indexOf('n') > -1) {
688            RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.2), String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
689            RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.4), String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
690            RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.6), String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
691            RGraph.Text(context, font_face, font_size, this.centerx, this.centery - (r * 0.8), String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
692            RGraph.Text(context, font_face, font_size, this.centerx, this.centery - r, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
693        }
694
695        // The "South" axis labels
696        if (axes.indexOf('s') > -1) {
697            RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.2), String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
698            RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.4), String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
699            RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.6), String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
700            RGraph.Text(context, font_face, font_size, this.centerx, this.centery + (r * 0.8), String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
701            RGraph.Text(context, font_face, font_size, this.centerx, this.centery + r, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
702        }
703       
704        // The "East" axis labels
705        if (axes.indexOf('e') > -1) {
706            RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.2), this.centery, String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
707            RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.4), this.centery, String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
708            RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.6), this.centery, String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
709            RGraph.Text(context, font_face, font_size, this.centerx + (r * 0.8), this.centery, String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
710            RGraph.Text(context, font_face, font_size, this.centerx + r, this.centery, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
711        }
712
713        // The "West" axis labels
714        if (axes.indexOf('w') > -1) {
715            RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.2), this.centery, String(Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
716            RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.4), this.centery, String(Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
717            RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.6), this.centery, String(Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
718            RGraph.Text(context, font_face, font_size, this.centerx - (r * 0.8), this.centery, String(Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
719            RGraph.Text(context, font_face, font_size, this.centerx - r, this.centery, String(Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals'))), 'center', 'center', true, false, color);
720        }
721
722        RGraph.Text(context, font_face, font_size, this.centerx,  this.centery, typeof(this.Get('chart.ymin')) == 'number' ? String(Number(this.Get('chart.ymin')).toFixed(this.Get('chart.scale.decimals'))) : '0', 'center', 'center', true, false, color);
723    }
724
725
726    /**
727    * Draws the circular labels that go around the charts
728    *
729    * @param labels array The labels that go around the chart
730    */
731    RGraph.Rose.prototype.DrawCircularLabels = function (context, labels, font_face, font_size, r)
732    {
733        var variant = this.Get('chart.variant');
734        var position = this.Get('chart.labels.position');
735        var r        = r + 10 + this.Get('chart.labels.offset');
736
737        for (var i=0; i<labels.length; ++i) {
738           
739            if (typeof(variant) == 'string' && variant == 'non-equi-angular') {
740
741                var a = Number(this.angles[i][0]) + ((this.angles[i][1] - this.angles[i][0]) / 2);
742                    a -= 90;
743                var halign = 'center'; // Default halign
744
745                var x = Math.cos(a / 57.29577866666) * (r + 10);
746                var y = Math.sin(a / 57.29577866666) * (r + 10);
747               
748                RGraph.Text(context, font_face, font_size, this.centerx + x, this.centery + y, String(labels[i]), 'center', halign);
749               
750            } else {
751
752                var a = (360 / labels.length) * (i + 1) - (360 / (labels.length * 2));
753                var a = a - 90 + (this.Get('chart.labels.position') == 'edge' ? ((360 / labels.length) / 2) : 0);
754                var halign = 'center'; // Default halign
755   
756                // Horizontal alignment
757                //if (a == 0) {
758                //    var halign = 'left';
759                //} else if (a == 180) {
760                //    var halign = 'right';
761                //}
762   
763                var x = Math.cos(a / 57.29577866666) * (r + 10);
764                var y = Math.sin(a / 57.29577866666) * (r + 10);
765   
766                RGraph.Text(context, font_face, font_size, this.centerx + x, this.centery + y, String(labels[i]), 'center', halign);
767            }
768        }
769    }
770
771
772    /**
773    * This function is for use with circular graph types, eg the Pie or Rose. Pass it your event object
774    * and it will pass you back the corresponding segment details as an array:
775    *
776    * [x, y, r, startAngle, endAngle]
777    *
778    * Angles are measured in degrees, and are measured from the "east" axis (just like the canvas).
779    *
780    * @param object e   Your event object
781    */
782    RGraph.Rose.prototype.getSegment = function (e)
783    {
784        RGraph.FixEventObject(e);
785
786        // The optional arg provides a way of allowing some accuracy (pixels)
787        var accuracy = arguments[1] ? arguments[1] : 0;
788
789        var obj         = e.target.__object__;
790        var canvas      = obj.canvas;
791        var context     = obj.context;
792        var mouseCoords = RGraph.getMouseXY(e);
793        var x           = mouseCoords[0] - obj.centerx;
794        var y           = mouseCoords[1] - obj.centery;
795        var r           = obj.radius;
796        var theta       = Math.atan(y / x); // RADIANS
797        var hyp         = y / Math.sin(theta);
798        var angles      = obj.angles;
799        var ret         = [];
800        var hyp         = (hyp < 0) ? hyp + accuracy : hyp - accuracy;
801
802
803
804        // Put theta in DEGREES
805        theta *= 57.3
806
807        // hyp should not be greater than radius if it's a Rose chart
808        if (obj.type == 'rose') {
809            if (   (isNaN(hyp) && Math.abs(mouseCoords[0]) < (obj.centerx - r) )
810                || (isNaN(hyp) && Math.abs(mouseCoords[0]) > (obj.centerx + r))
811                || (!isNaN(hyp) && Math.abs(hyp) > r)) {
812                return;
813            }
814        }
815
816        /**
817        * Account for the correct quadrant
818        */
819        if (x < 0 && y >= 0) {
820            theta += 180;
821        } else if (x < 0 && y < 0) {
822            theta += 180;
823        } else if (x > 0 && y < 0) {
824            theta += 360;
825        }
826
827        /**
828        * Account for the rose chart angle displacement
829        */
830        theta += 90;
831
832        if (theta > 360) {
833            theta -= 360;
834        }
835
836        hyp = Math.abs(hyp);
837
838        for (var i=0; i<angles.length; ++i) {
839            if (theta >= angles[i][0] && theta < angles[i][1] && hyp > angles[i][2] && hyp < angles[i][3]) {
840
841                if (!(hyp > angles[i][2] && hyp < angles[i][3])) {
842                    return null;
843                }
844
845                if (!hyp) {
846                    return null;
847                }
848
849                ret[0] = obj.centerx;
850                ret[1] = obj.centery;
851                ret[2] = angles[i][2]; // Start angle
852                ret[3] = angles[i][3]; // End angle
853
854                ret[4] = angles[i][0]; // Start radius
855                ret[5] = angles[i][1]; // End radius
856                ret[6] = i;
857
858                ret[4] -= 90;
859                ret[5] -= 90;
860           
861                if (x > 0 && y < 0) {
862                    ret[4] += 360;
863                    ret[5] += 360;
864                }
865               
866                if (ret[4] < 0) ret[4] += 360;
867                if (ret[5] > 360) ret[5] -= 360;
868
869                return ret;
870            }
871        }
872       
873        return null;
874    }
Note: See TracBrowser for help on using the repository browser.