summaryrefslogtreecommitdiff
path: root/schall/static/RGraph/libraries/RGraph.rose.js
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2011-10-23 21:14:40 +0200
committerYves Fischer <yvesf-git@xapek.org>2011-10-30 11:33:54 +0100
commit770ba5201f5c60b2bb36602ff9d359f641e33125 (patch)
tree2200757f04efbc281c4b3714bfe2e4fe911193b6 /schall/static/RGraph/libraries/RGraph.rose.js
parent77f5e686612898974e13f2a5df57c20e4e529363 (diff)
downloadmini-octopus-770ba5201f5c60b2bb36602ff9d359f641e33125.tar.gz
mini-octopus-770ba5201f5c60b2bb36602ff9d359f641e33125.zip
Charting with flask, rgraph and custom "timeseries database"
Diffstat (limited to 'schall/static/RGraph/libraries/RGraph.rose.js')
-rw-r--r--schall/static/RGraph/libraries/RGraph.rose.js894
1 files changed, 894 insertions, 0 deletions
diff --git a/schall/static/RGraph/libraries/RGraph.rose.js b/schall/static/RGraph/libraries/RGraph.rose.js
new file mode 100644
index 0000000..99bf353
--- /dev/null
+++ b/schall/static/RGraph/libraries/RGraph.rose.js
@@ -0,0 +1,894 @@
+ /**
+ * o------------------------------------------------------------------------------o
+ * | This file is part of the RGraph package - you can learn more at: |
+ * | |
+ * | http://www.rgraph.net |
+ * | |
+ * | This package is licensed under the RGraph license. For all kinds of business |
+ * | purposes there is a small one-time licensing fee to pay and for non |
+ * | commercial purposes it is free to use. You can read the full license here: |
+ * | |
+ * | http://www.rgraph.net/LICENSE.txt |
+ * o------------------------------------------------------------------------------o
+ */
+
+ if (typeof(RGraph) == 'undefined') RGraph = {};
+
+ /**
+ * The rose chart constuctor
+ *
+ * @param object canvas
+ * @param array data
+ */
+ RGraph.Rose = function (id, data)
+ {
+ this.id = id;
+ this.canvas = document.getElementById(id);
+ this.context = this.canvas.getContext('2d');
+ this.data = data;
+ this.canvas.__object__ = this;
+ this.type = 'rose';
+ this.isRGraph = true;
+
+
+ /**
+ * Compatibility with older browsers
+ */
+ RGraph.OldBrowserCompat(this.context);
+
+
+ this.centerx = 0;
+ this.centery = 0;
+ this.radius = 0;
+ this.max = 0;
+
+ this.properties = {
+ 'chart.radius': null,
+ 'chart.colors': ['red', 'rgb(0,255,255)', 'rgb(0,255,0)', 'gray', 'blue', 'rgb(255,128,255)','green', 'pink', 'gray', 'aqua'],
+ 'chart.colors.sequential': false,
+ 'chart.colors.alpha': null,
+ 'chart.margin': 0,
+ 'chart.strokestyle': 'rgba(0,0,0,0.5)',
+ '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': null,
+ 'chart.title.bold': true,
+ 'chart.title.font': null,
+ 'chart.labels': null,
+ 'chart.labels.position': 'center',
+ 'chart.labels.axes': 'nsew',
+ 'chart.labels.offset': 0,
+ 'chart.text.color': 'black',
+ 'chart.text.font': 'Verdana',
+ 'chart.text.size': 10,
+ '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': true,
+ 'chart.key.position.x': null,
+ 'chart.key.position.y': null,
+ 'chart.key.color.shape': 'square',
+ 'chart.key.rounded': true,
+ 'chart.key.linewidth': 1,
+ '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.stroke': 'black',
+ 'chart.highlight.fill': 'rgba(255,255,255,0.5)',
+ '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.mode': 'canvas',
+ 'chart.zoom.thumbnail.width': 75,
+ 'chart.zoom.thumbnail.height': 75,
+ 'chart.zoom.background': true,
+ 'chart.zoom.action': 'zoom',
+ 'chart.resizable': false,
+ 'chart.resize.handle.adjust': [0,0],
+ 'chart.resize.handle.background': null,
+ 'chart.adjustable': false,
+ 'chart.ymax': null,
+ 'chart.ymin': 0,
+ 'chart.scale.decimals': null,
+ 'chart.variant': 'stacked',
+ 'chart.animation.grow.factor': 1
+ }
+
+
+ /**
+ * Set the .getShape commonly named method
+ */
+ this.getShape = this.getSegment;
+ }
+
+
+ /**
+ * A simple setter
+ *
+ * @param string name The name of the property to set
+ * @param string value The value of the property
+ */
+ RGraph.Rose.prototype.Set = function (name, value)
+ {
+ this.properties[name.toLowerCase()] = value;
+ }
+
+
+ /**
+ * A simple getter
+ *
+ * @param string name The name of the property to get
+ */
+ RGraph.Rose.prototype.Get = function (name)
+ {
+ return this.properties[name.toLowerCase()];
+ }
+
+
+ /**
+ * This method draws the rose chart
+ */
+ RGraph.Rose.prototype.Draw = function ()
+ {
+ /**
+ * Fire the onbeforedraw event
+ */
+ RGraph.FireCustomEvent(this, 'onbeforedraw');
+
+ /**
+ * Clear all of this canvases event handlers (the ones installed by RGraph)
+ */
+ RGraph.ClearEventListeners(this.id);
+
+
+ /**
+ * This doesn't affect the chart, but is used for compatibility
+ */
+ this.gutterLeft = this.Get('chart.gutter.left');
+ this.gutterRight = this.Get('chart.gutter.right');
+ this.gutterTop = this.Get('chart.gutter.top');
+ this.gutterBottom = this.Get('chart.gutter.bottom');
+
+ // Calculate the radius
+ this.radius = (Math.min(RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight, RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2);
+ this.centerx = RGraph.GetWidth(this) / 2;
+ this.centery = RGraph.GetHeight(this) / 2;
+ this.angles = [];
+ this.total = 0;
+ this.startRadians = 0;
+
+ // User specified radius
+ if (typeof(this.Get('chart.radius')) == 'number') {
+ this.radius = this.Get('chart.radius');
+ }
+
+ /**
+ * Change the centerx marginally if the key is defined
+ */
+ if (this.Get('chart.key') && this.Get('chart.key').length > 0 && this.Get('chart.key').length >= 3) {
+ this.centerx = this.centerx - this.Get('chart.gutter.right') + 5;
+ }
+
+ this.DrawBackground();
+ this.DrawRose();
+ this.DrawLabels();
+
+ /**
+ * Setup the context menu if required
+ */
+ if (this.Get('chart.contextmenu')) {
+ RGraph.ShowContext(this);
+ }
+
+ /**
+ * Tooltips
+ */
+ if (this.Get('chart.tooltips')) {
+
+ /**
+ * Register this object for redrawing
+ */
+ RGraph.Register(this);
+
+ /**
+ * The onclick event
+ */
+ var canvas_onclick_func = function (e)
+ {
+ var obj = e.target.__object__;
+ var canvas = e.target;
+ var context = canvas.getContext('2d');
+
+ e = RGraph.FixEventObject(e);
+
+ RGraph.Redraw();
+
+ var segment = obj.getSegment(e);
+
+ if (segment && obj.Get('chart.tooltips')) {
+
+ /**
+ * Get the tooltip text
+ */
+ if (typeof(obj.Get('chart.tooltips')) == 'function') {
+ var text = String(obj.Get('chart.tooltips')(segment[6]));
+ } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[segment[6]]) == 'function') {
+ var text = String(obj.Get('chart.tooltips')[segment[6]](segment[6]));
+ } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[segment[6]]) == 'string' || typeof(obj.Get('chart.tooltips')[segment[6]]) == 'number')) {
+ var text = String(obj.Get('chart.tooltips')[segment[6]]);
+ } else {
+ var text = null;
+ }
+
+ if (text) {
+ context.beginPath();
+ context.strokeStyle = obj.Get('chart.highlight.stroke');
+ context.fillStyle = obj.Get('chart.highlight.fill');
+
+ // This highlights the chart
+ context.arc(obj.centerx, obj.centery, segment[3], segment[4] / 57.3, segment[5] / 57.3, false);
+ context.arc(obj.centerx, obj.centery, segment[2] + 0.01, segment[5] / 57.3, segment[4] / 57.3, true);
+
+ context.closePath();
+
+ context.fill();
+ context.stroke();
+
+ context.strokeStyle = 'rgba(0,0,0,0)';
+
+ // Taken out on 12th June 2011
+ //obj.DrawLabels();
+
+ /**
+ * Show the tooltip
+ */
+ RGraph.Tooltip(canvas, text, e.pageX, e.pageY, segment[6]);
+
+ e.stopPropagation();
+ }
+
+ return;
+ }
+ }
+ this.canvas.addEventListener('click', canvas_onclick_func, false);
+ RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
+
+
+ /**
+ * The onmousemove event
+ */
+ var canvas_onmousemove_func = function (e)
+ {
+
+ var obj = e.target.__object__;
+ var canvas = e.target;
+ var context = canvas.getContext('2d');
+
+ e = RGraph.FixEventObject(e);
+
+ var segment = obj.getSegment(e);
+
+ if (segment && obj.Get('chart.tooltips')) {
+
+ /**
+ * Get the tooltip text
+ */
+ if (typeof(obj.Get('chart.tooltips')) == 'function') {
+ var text = String(obj.Get('chart.tooltips')(segment[6]));
+ } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[segment[6]]) == 'function') {
+ var text = String(obj.Get('chart.tooltips')[segment[6]](segment[6]));
+ } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[segment[6]]) == 'string' || typeof(obj.Get('chart.tooltips')[segment[6]]) == 'number')) {
+ var text = String(obj.Get('chart.tooltips')[segment[6]]);
+ } else {
+ var text = null;
+ }
+
+ if (text) {
+ canvas.style.cursor = 'pointer';
+
+ /*******************************************************
+ * This is here in case tooltips are using the
+ * onmousemove event
+ *******************************************************/
+ if (obj.Get('chart.tooltips.event') == 'onmousemove') {
+ if (!RGraph.Registry.Get('chart.tooltip') || RGraph.Registry.Get('chart.tooltip').__index__ != segment[6]) {
+ canvas_onclick_func(e);
+ }
+ }
+
+ } else {
+ canvas.style.cursor = 'default';
+ }
+
+ return;
+ }
+
+ canvas.style.cursor = 'default';
+ }
+ this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
+ RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
+ }
+
+ /**
+ * If the canvas is annotatable, do install the event handlers
+ */
+ if (this.Get('chart.annotatable')) {
+ RGraph.Annotate(this);
+ }
+
+ /**
+ * This bit shows the mini zoom window if requested
+ */
+ if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
+ RGraph.ShowZoomWindow(this);
+ }
+
+
+ /**
+ * This function enables resizing
+ */
+ if (this.Get('chart.resizable')) {
+ RGraph.AllowResizing(this);
+ }
+
+
+ /**
+ * This function enables adjusting
+ */
+ if (this.Get('chart.adjustable')) {
+ RGraph.AllowAdjusting(this);
+ }
+
+ /**
+ * Fire the RGraph ondraw event
+ */
+ RGraph.FireCustomEvent(this, 'ondraw');
+ }
+
+ /**
+ * This method draws the rose charts background
+ */
+ RGraph.Rose.prototype.DrawBackground = function ()
+ {
+ this.context.lineWidth = 1;
+
+ // Draw the background grey circles
+ this.context.beginPath();
+ this.context.strokeStyle = '#ccc';
+ for (var i=15; i<this.radius - (RGraph.isIE8() ? 5 : 0); i+=15) {// Radius must be greater than 0 for Opera to work
+
+ //this.context.moveTo(this.centerx + i, this.centery);
+
+ // Radius must be greater than 0 for Opera to work
+ this.context.arc(this.centerx, this.centery, i, 0, (2 * Math.PI), 0);
+ }
+ this.context.stroke();
+
+ // Draw the background lines that go from the center outwards
+ this.context.beginPath();
+ for (var i=15; i<360; i+=15) {
+
+ // Radius must be greater than 0 for Opera to work
+ 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
+
+ this.context.lineTo(this.centerx, this.centery);
+ }
+ this.context.stroke();
+
+ this.context.beginPath();
+ this.context.strokeStyle = 'black';
+
+ // Draw the X axis
+ this.context.moveTo(this.centerx - this.radius, this.centery);
+ this.context.lineTo(this.centerx + this.radius, this.centery);
+
+ // Draw the X ends
+ this.context.moveTo(this.centerx - this.radius, this.centery - 5);
+ this.context.lineTo(this.centerx - this.radius, this.centery + 5);
+ this.context.moveTo(this.centerx + this.radius, this.centery - 5);
+ this.context.lineTo(this.centerx + this.radius, this.centery + 5);
+
+ // Draw the X check marks
+ for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=20) {
+ this.context.moveTo(i, this.centery - 3);
+ this.context.lineTo(i, this.centery + 3);
+ }
+
+ // Draw the Y check marks
+ for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=20) {
+ this.context.moveTo(this.centerx - 3, i);
+ this.context.lineTo(this.centerx + 3, i);
+ }
+
+ // Draw the Y axis
+ this.context.moveTo(this.centerx, this.centery - this.radius);
+ this.context.lineTo(this.centerx, this.centery + this.radius);
+
+ // Draw the Y ends
+ this.context.moveTo(this.centerx - 5, this.centery - this.radius);
+ this.context.lineTo(this.centerx + 5, this.centery - this.radius);
+
+ this.context.moveTo(this.centerx - 5, this.centery + this.radius);
+ this.context.lineTo(this.centerx + 5, this.centery + this.radius);
+
+ // Stroke it
+ this.context.closePath();
+ this.context.stroke();
+ }
+
+
+ /**
+ * This method draws the data on the graph
+ */
+ RGraph.Rose.prototype.DrawRose = function ()
+ {
+ var max = 0;
+ var data = this.data;
+ var margin = RGraph.degrees2Radians(this.Get('chart.margin'));
+
+ // Must be at least two data points
+ //if (data.length < 2) {
+ // alert('[ROSE] Must be at least two data points! [' + data + ']');
+ // return;
+ //}
+
+ // Work out the maximum value and the sum
+ if (!this.Get('chart.ymax')) {
+ // Work out the max
+ for (var i=0; i<data.length; ++i) {
+ if (typeof(data[i]) == 'number') {
+ max = Math.max(max, data[i]);
+ } else if (typeof(data[i]) == 'object' && this.Get('chart.variant') == 'non-equi-angular') {
+ max = Math.max(max, data[i][0]);
+
+ // Fallback is stacked
+ } else {
+ max = Math.max(max, RGraph.array_sum(data[i]));
+ }
+ }
+
+ this.scale = RGraph.getScale(max, this);
+ this.max = this.scale[4];
+ } else {
+ var ymax = this.Get('chart.ymax');
+ var ymin = this.Get('chart.ymin');
+
+ this.scale = [
+ ((ymax - ymin) * 0.2) + ymin,
+ ((ymax - ymin) * 0.4) + ymin,
+ ((ymax - ymin) * 0.6) + ymin,
+ ((ymax - ymin) * 0.8) + ymin,
+ ((ymax - ymin) * 1.0) + ymin
+ ];
+ this.max = this.scale[4];
+ }
+
+ this.sum = RGraph.array_sum(data);
+
+ // Move to the centre
+ this.context.moveTo(this.centerx, this.centery);
+
+ this.context.stroke(); // Stroke the background so it stays grey
+
+ // Transparency
+ if (this.Get('chart.colors.alpha')) {
+ this.context.globalAlpha = this.Get('chart.colors.alpha');
+ }
+
+ /*******************************************************
+ * A non-equi-angular Rose chart
+ *******************************************************/
+ if (typeof(this.Get('chart.variant')) == 'string' && this.Get('chart.variant') == 'non-equi-angular') {
+ /*******************************************************
+ * NON-EQUI-ANGULAR GOES HERE
+ *******************************************************/
+ var total=0;
+ for (var i=0; i<data.length; ++i) {
+ total += data[i][1];
+ }
+
+
+ for (var i=0; i<this.data.length; ++i) {
+
+ var segmentRadians = (this.data[i][1] / total) * (2 * Math.PI);
+ var radius = ((this.data[i][0] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
+
+ this.context.strokeStyle = this.Get('chart.strokestyle');
+ this.context.fillStyle = this.Get('chart.colors')[0];
+
+ if (this.Get('chart.colors.sequential')) {
+ this.context.fillStyle = this.Get('chart.colors')[i];
+ }
+
+ this.context.beginPath(); // Begin the segment
+ this.context.arc(this.centerx,
+ this.centery,
+ radius,
+ this.startRadians - (Math.PI / 2) + margin,
+ this.startRadians + segmentRadians - (Math.PI / 2) - margin,
+ 0);
+ this.context.lineTo(this.centerx, this.centery);
+ this.context.closePath(); // End the segment
+
+ this.context.stroke();
+ this.context.fill();
+
+ // Store the start and end angles
+ this.angles.push([
+ ((this.startRadians - (Math.PI / 2) + margin) * 57.3) + 90,
+ (((this.startRadians + segmentRadians) - (Math.PI / 2) - margin) * 57.3) + 90,
+ 0,
+ radius
+ ]);
+
+ this.startRadians += segmentRadians;
+ }
+ } else {
+ /*******************************************************
+ * Draw regular segments here
+ *******************************************************/
+ for (var i=0; i<this.data.length; ++i) {
+
+ this.context.strokeStyle = this.Get('chart.strokestyle');
+ this.context.fillStyle = this.Get('chart.colors')[0];
+
+ /*******************************************************
+ * This allows sequential colors
+ *******************************************************/
+ if (this.Get('chart.colors.sequential')) {
+ this.context.fillStyle = this.Get('chart.colors')[i];
+ }
+
+ var segmentRadians = (1 / this.data.length) * (2 * Math.PI);
+
+ if (typeof(this.data[i]) == 'number') {
+ this.context.beginPath(); // Begin the segment
+
+ var radius = ((this.data[i] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
+
+ this.context.arc(this.centerx,
+ this.centery,
+ radius * this.Get('chart.animation.grow.factor'),
+ (this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin,
+ (this.startRadians * this.Get('chart.animation.grow.factor')) + (segmentRadians) - (Math.PI / 2) - margin,
+ 0);
+ this.context.lineTo(this.centerx, this.centery);
+ this.context.closePath(); // End the segment
+ this.context.stroke();
+ this.context.fill();
+
+ // Store the start and end angles
+ this.angles.push([
+ (((this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin) * 57.3) + 90,
+ ((((this.startRadians * this.Get('chart.animation.grow.factor')) + segmentRadians) - (Math.PI / 2) - margin) * 57.3) + 90,
+ 0,
+ radius * this.Get('chart.animation.grow.factor')
+ ]);
+ /*******************************************************
+ * Draw a stacked segment
+ *******************************************************/
+ } else if (typeof(this.data[i]) == 'object') {
+
+ var margin = this.Get('chart.margin') / (180 / Math.PI);
+
+ for (var j=0; j<this.data[i].length; ++j) {
+
+ this.context.fillStyle = this.Get('chart.colors')[j];
+ if (j == 0) {
+ this.context.beginPath(); // Begin the segment
+ var startRadius = 0;
+ var endRadius = ((this.data[i][j] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10);
+
+ this.context.arc(this.centerx,
+ this.centery,
+ endRadius * this.Get('chart.animation.grow.factor'),
+ (this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin,
+ (this.startRadians * this.Get('chart.animation.grow.factor'))+ segmentRadians - (Math.PI / 2) - margin,
+ 0);
+ this.context.lineTo(this.centerx, this.centery);
+ this.context.closePath(); // End the segment
+ this.context.stroke();
+ this.context.fill();
+
+ this.angles.push([
+ (((this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin) * 57.3) + 90 ,
+ ((((this.startRadians * this.Get('chart.animation.grow.factor')) + segmentRadians) - (Math.PI / 2) - margin) * 57.3) + 90,
+ 0,
+ endRadius * this.Get('chart.animation.grow.factor')
+ ]);
+
+ } else {
+
+ this.context.beginPath(); // Begin the segment
+ var startRadius = endRadius; // This comes from the prior iteration of this loop
+ var endRadius = (((this.data[i][j] - this.Get('chart.ymin')) / (this.max - this.Get('chart.ymin'))) * (this.radius - 10)) + startRadius;
+
+ this.context.arc(this.centerx,
+ this.centery,
+ startRadius * this.Get('chart.animation.grow.factor'),
+ (this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin,
+ (this.startRadians * this.Get('chart.animation.grow.factor')) + segmentRadians - (Math.PI / 2) - margin,
+ 0);
+
+ this.context.arc(this.centerx,
+ this.centery,
+ endRadius * this.Get('chart.animation.grow.factor'),
+ (this.startRadians * this.Get('chart.animation.grow.factor')) + segmentRadians - (Math.PI / 2) - margin,
+ (this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin,
+ true);
+
+ this.context.closePath(); // End the segment
+ this.context.stroke();
+ this.context.fill();
+
+ this.angles.push([
+ (((this.startRadians * this.Get('chart.animation.grow.factor')) - (Math.PI / 2) + margin) * 57.3) + 90,
+ (((this.startRadians * this.Get('chart.animation.grow.factor')) + segmentRadians - (Math.PI / 2) - margin) * 57.3) + 90,
+ startRadius * this.Get('chart.animation.grow.factor'),
+ endRadius * this.Get('chart.animation.grow.factor')
+ ]);
+ }
+ }
+ }
+
+ this.startRadians += segmentRadians;
+ }
+ }
+
+ // Turn off the transparency
+ if (this.Get('chart.colors.alpha')) {
+ this.context.globalAlpha = 1;
+ }
+
+ // Draw the title if any has been set
+ if (this.Get('chart.title')) {
+ RGraph.DrawTitle(this.canvas,
+ this.Get('chart.title'),
+ (this.canvas.height / 2) - this.radius,
+ this.centerx,
+ this.Get('chart.title.size') ? this.Get('chart.title.size') : this.Get('chart.text.size') + 2);
+ }
+ }
+
+
+ /**
+ * Unsuprisingly, draws the labels
+ */
+ RGraph.Rose.prototype.DrawLabels = function ()
+ {
+ this.context.lineWidth = 1;
+ var key = this.Get('chart.key');
+
+ if (key && key.length) {
+ RGraph.DrawKey(this, key, this.Get('chart.colors'));
+ }
+
+ // Set the color to black
+ this.context.fillStyle = 'black';
+ this.context.strokeStyle = 'black';
+
+ var r = this.radius - 10;
+ var font_face = this.Get('chart.text.font');
+ var font_size = this.Get('chart.text.size');
+ var context = this.context;
+ var axes = this.Get('chart.labels.axes').toLowerCase();
+
+ // Draw any labels
+
+ if (typeof(this.Get('chart.labels')) == 'object' && this.Get('chart.labels')) {
+ this.DrawCircularLabels(context, this.Get('chart.labels'), font_face, font_size, r + 10);
+ }
+
+
+ var color = 'rgba(255,255,255,0.8)';
+
+ // The "North" axis labels
+ if (axes.indexOf('n') > -1) {
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ // The "South" axis labels
+ if (axes.indexOf('s') > -1) {
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ // The "East" axis labels
+ if (axes.indexOf('e') > -1) {
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ // The "West" axis labels
+ if (axes.indexOf('w') > -1) {
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ }
+
+ 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);
+ }
+
+
+ /**
+ * Draws the circular labels that go around the charts
+ *
+ * @param labels array The labels that go around the chart
+ */
+ RGraph.Rose.prototype.DrawCircularLabels = function (context, labels, font_face, font_size, r)
+ {
+ var variant = this.Get('chart.variant');
+ var position = this.Get('chart.labels.position');
+ var r = r + 10 + this.Get('chart.labels.offset');
+
+ for (var i=0; i<labels.length; ++i) {
+
+ if (typeof(variant) == 'string' && variant == 'non-equi-angular') {
+
+ var a = Number(this.angles[i][0]) + ((this.angles[i][1] - this.angles[i][0]) / 2);
+ a -= 90;
+ var halign = 'center'; // Default halign
+
+ var x = Math.cos(a / 57.29577866666) * (r + 10);
+ var y = Math.sin(a / 57.29577866666) * (r + 10);
+
+ RGraph.Text(context, font_face, font_size, this.centerx + x, this.centery + y, String(labels[i]), 'center', halign);
+
+ } else {
+
+ var a = (360 / labels.length) * (i + 1) - (360 / (labels.length * 2));
+ var a = a - 90 + (this.Get('chart.labels.position') == 'edge' ? ((360 / labels.length) / 2) : 0);
+ var halign = 'center'; // Default halign
+
+ // Horizontal alignment
+ //if (a == 0) {
+ // var halign = 'left';
+ //} else if (a == 180) {
+ // var halign = 'right';
+ //}
+
+ var x = Math.cos(a / 57.29577866666) * (r + 10);
+ var y = Math.sin(a / 57.29577866666) * (r + 10);
+
+ RGraph.Text(context, font_face, font_size, this.centerx + x, this.centery + y, String(labels[i]), 'center', halign);
+ }
+ }
+ }
+
+
+ /**
+ * This function is for use with circular graph types, eg the Pie or Rose. Pass it your event object
+ * and it will pass you back the corresponding segment details as an array:
+ *
+ * [x, y, r, startAngle, endAngle]
+ *
+ * Angles are measured in degrees, and are measured from the "east" axis (just like the canvas).
+ *
+ * @param object e Your event object
+ */
+ RGraph.Rose.prototype.getSegment = function (e)
+ {
+ RGraph.FixEventObject(e);
+
+ // The optional arg provides a way of allowing some accuracy (pixels)
+ var accuracy = arguments[1] ? arguments[1] : 0;
+
+ var obj = e.target.__object__;
+ var canvas = obj.canvas;
+ var context = obj.context;
+ var mouseCoords = RGraph.getMouseXY(e);
+ var x = mouseCoords[0] - obj.centerx;
+ var y = mouseCoords[1] - obj.centery;
+ var r = obj.radius;
+ var theta = Math.atan(y / x); // RADIANS
+ var hyp = y / Math.sin(theta);
+ var angles = obj.angles;
+ var ret = [];
+ var hyp = (hyp < 0) ? hyp + accuracy : hyp - accuracy;
+
+
+
+ // Put theta in DEGREES
+ theta *= 57.3
+
+ // hyp should not be greater than radius if it's a Rose chart
+ if (obj.type == 'rose') {
+ if ( (isNaN(hyp) && Math.abs(mouseCoords[0]) < (obj.centerx - r) )
+ || (isNaN(hyp) && Math.abs(mouseCoords[0]) > (obj.centerx + r))
+ || (!isNaN(hyp) && Math.abs(hyp) > r)) {
+ return;
+ }
+ }
+
+ /**
+ * Account for the correct quadrant
+ */
+ if (x < 0 && y >= 0) {
+ theta += 180;
+ } else if (x < 0 && y < 0) {
+ theta += 180;
+ } else if (x > 0 && y < 0) {
+ theta += 360;
+ }
+
+ /**
+ * Account for the rose chart angle displacement
+ */
+ theta += 90;
+
+ if (theta > 360) {
+ theta -= 360;
+ }
+
+ hyp = Math.abs(hyp);
+
+ for (var i=0; i<angles.length; ++i) {
+ if (theta >= angles[i][0] && theta < angles[i][1] && hyp > angles[i][2] && hyp < angles[i][3]) {
+
+ if (!(hyp > angles[i][2] && hyp < angles[i][3])) {
+ return null;
+ }
+
+ if (!hyp) {
+ return null;
+ }
+
+ ret[0] = obj.centerx;
+ ret[1] = obj.centery;
+ ret[2] = angles[i][2]; // Start angle
+ ret[3] = angles[i][3]; // End angle
+
+ ret[4] = angles[i][0]; // Start radius
+ ret[5] = angles[i][1]; // End radius
+ ret[6] = i;
+
+ ret[4] -= 90;
+ ret[5] -= 90;
+
+ if (x > 0 && y < 0) {
+ ret[4] += 360;
+ ret[5] += 360;
+ }
+
+ if (ret[4] < 0) ret[4] += 360;
+ if (ret[5] > 360) ret[5] -= 360;
+
+ return ret;
+ }
+ }
+
+ return null;
+ } \ No newline at end of file