diff options
author | Yves Fischer <yvesf-git@xapek.org> | 2011-10-23 21:14:40 +0200 |
---|---|---|
committer | Yves Fischer <yvesf-git@xapek.org> | 2011-10-30 11:33:54 +0100 |
commit | 770ba5201f5c60b2bb36602ff9d359f641e33125 (patch) | |
tree | 2200757f04efbc281c4b3714bfe2e4fe911193b6 /schall/static/RGraph/libraries/RGraph.pie.js | |
parent | 77f5e686612898974e13f2a5df57c20e4e529363 (diff) | |
download | mini-octopus-770ba5201f5c60b2bb36602ff9d359f641e33125.tar.gz mini-octopus-770ba5201f5c60b2bb36602ff9d359f641e33125.zip |
Charting with flask, rgraph and custom "timeseries database"
Diffstat (limited to 'schall/static/RGraph/libraries/RGraph.pie.js')
-rw-r--r-- | schall/static/RGraph/libraries/RGraph.pie.js | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/schall/static/RGraph/libraries/RGraph.pie.js b/schall/static/RGraph/libraries/RGraph.pie.js new file mode 100644 index 0000000..26f688e --- /dev/null +++ b/schall/static/RGraph/libraries/RGraph.pie.js @@ -0,0 +1,1042 @@ + /** + * 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 pie chart constructor + * + * @param data array The data to be represented on the pie chart + */ + RGraph.Pie = function (id, data) + { + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext("2d"); + this.canvas.__object__ = this; + this.total = 0; + this.subTotal = 0; + this.angles = []; + this.data = data; + this.properties = []; + this.type = 'pie'; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + this.properties = { + 'chart.colors': ['rgb(255,0,0)', '#ddd', 'rgb(0,255,0)', 'rgb(0,0,255)', 'pink', 'yellow', '#000'], + 'chart.strokestyle': '#999', + 'chart.linewidth': 1, + 'chart.labels': [], + 'chart.labels.sticks': false, + 'chart.labels.sticks.length': 7, + 'chart.labels.sticks.color': '#aaa', + 'chart.segments': [], + 'chart.gutter.left': 25, + 'chart.gutter.right': 25, + 'chart.gutter.top': 25, + 'chart.gutter.bottom': 25, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': 0.5, + 'chart.title.bold': true, + 'chart.title.font': null, + 'chart.shadow': false, + 'chart.shadow.color': 'rgba(0,0,0,0.5)', + 'chart.shadow.offsetx': 3, + 'chart.shadow.offsety': 3, + 'chart.shadow.blur': 3, + 'chart.text.size': 10, + 'chart.text.color': 'black', + 'chart.text.font': 'Verdana', + 'chart.contextmenu': null, + 'chart.tooltips': [], + 'chart.tooltips.event': 'onclick', + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.highlight.style': '3d', + 'chart.highlight.style.2d.fill': 'rgba(255,255,255,0.5)', + 'chart.highlight.style.2d.stroke': 'rgba(255,255,255,0)', + 'chart.centerx': null, + 'chart.centery': null, + 'chart.radius': null, + 'chart.border': false, + 'chart.border.color': 'rgba(255,255,255,0.5)', + 'chart.key': null, + 'chart.key.background': 'white', + 'chart.key.position': 'graph', + 'chart.key.halign': 'right', + 'chart.key.shadow': false, + 'chart.key.shadow.color': '#666', + 'chart.key.shadow.blur': 3, + 'chart.key.shadow.offsetx': 2, + 'chart.key.shadow.offsety': 2, + 'chart.key.position.gutter.boxed': 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.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.align': 'center', + '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.variant': 'pie', + 'chart.variant.donut.color': 'white', + 'chart.exploded': [], + 'chart.effect.roundrobin.multiplier': 1 + } + + /** + * Calculate the total + */ + for (var i=0,len=data.length; i<len; i++) { + this.total += data[i]; + } + + + /** + * Set the .getShape commonly named method + */ + this.getShape = this.getSegment; + } + + + /** + * A generic setter + */ + RGraph.Pie.prototype.Set = function (name, value) + { + if (name == 'chart.highlight.style.2d.color') { + name = 'chart.highlight.style.2d.fill'; + } + + this.properties[name] = value; + } + + + /** + * A generic getter + */ + RGraph.Pie.prototype.Get = function (name) + { + if (name == 'chart.highlight.style.2d.color') { + name = 'chart.highlight.style.2d.fill'; + } + + return this.properties[name]; + } + + + /** + * This draws the pie chart + */ + RGraph.Pie.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + + /** + * This is new in May 2011 and facilitates indiviual gutter settings, + * eg chart.gutter.left + */ + 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'); + + /** + * Reset this to an empty array + */ + this.Set('chart.segments', []); + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + + this.radius = this.Get('chart.radius') ? this.Get('chart.radius') : this.getRadius(); + // this.centerx now defined below + this.centery = ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop; + this.subTotal = 0; + this.angles = []; + + /** + * Allow the specification of a custom centery + */ + if (typeof(this.Get('chart.centery')) == 'number') { + this.centery = this.Get('chart.centery'); + } + + /** + * Alignment (Pie is center aligned by default) Only if centerx is not defined - donut defines the centerx + */ + if (this.Get('chart.align') == 'left') { + this.centerx = this.radius + this.gutterLeft; + + } else if (this.Get('chart.align') == 'right') { + this.centerx = this.canvas.width - this.radius - this.gutterRight; + + } else { + this.centerx = this.canvas.width / 2; + } + + /** + * Allow the specification of a custom centerx + */ + if (typeof(this.Get('chart.centerx')) == 'number') { + this.centerx = this.Get('chart.centerx'); + } + + /** + * Draw the shadow if required + */ + if (this.Get('chart.shadow') && 0) { + + var offsetx = document.all ? this.Get('chart.shadow.offsetx') : 0; + var offsety = document.all ? this.Get('chart.shadow.offsety') : 0; + + this.context.beginPath(); + this.context.fillStyle = this.Get('chart.shadow.color'); + + this.context.shadowColor = this.Get('chart.shadow.color'); + this.context.shadowBlur = this.Get('chart.shadow.blur'); + this.context.shadowOffsetX = this.Get('chart.shadow.offsetx'); + this.context.shadowOffsetY = this.Get('chart.shadow.offsety'); + + this.context.arc(this.centerx + offsetx, this.centery + offsety, this.radius, 0, 6.28, 0); + + this.context.fill(); + + // Now turn off the shadow + RGraph.NoShadow(this); + } + + /** + * The total of the array of values + */ + this.total = RGraph.array_sum(this.data); + + for (var i=0,len=this.data.length; i<len; i++) { + + var angle = ((this.data[i] / this.total) * 360); + + // Draw the segment + this.DrawSegment(angle,this.Get('chart.colors')[i],i == (this.data.length - 1), i); + } + + RGraph.NoShadow(this); + + + /** + * Redraw the seperating lines + */ + this.DrawBorders(); + + /** + * Now draw the segments again with shadow turned off. This is always performed, + * not just if the shadow is on. + */ + + for (var i=0; i<this.angles.length; i++) { + + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.strokestyle'); + this.context.fillStyle = this.Get('chart.colors')[i]; + this.context.moveTo(this.angles[i][2], this.angles[i][3]); + 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); + this.context.lineTo(this.angles[i][2], this.angles[i][3]); + this.context.closePath(); + this.context.fill(); + this.context.stroke(); + } + + + + /** + * Draw label sticks + */ + if (this.Get('chart.labels.sticks')) { + + this.DrawSticks(); + + // Redraw the border going around the Pie chart if the stroke style is NOT white + var strokeStyle = this.Get('chart.strokestyle'); + var isWhite = strokeStyle == 'white' || strokeStyle == '#fff' || strokeStyle == '#fffffff' || strokeStyle == 'rgb(255,255,255)' || strokeStyle == 'rgba(255,255,255,0)'; + + if (!isWhite || (isWhite && this.Get('chart.shadow'))) { + // Again (?) + this.DrawBorders(); + } + } + + /** + * Draw the labels + */ + this.DrawLabels(); + + /** + * Draw the title + */ + if (this.Get('chart.align') == 'left') { + var centerx = this.radius + this.Get('chart.gutter.left'); + + } else if (this.Get('chart.align') == 'right') { + var centerx = RGraph.GetWidth(this) - (this.radius + this.gutterRight); + + } else { + var centerx = null; + } + + RGraph.DrawTitle(this.canvas, + this.Get('chart.title'), + (this.canvas.height / 2) - this.radius - 5, + centerx, + this.Get('chart.title.size') ? this.Get('chart.title.size') : this.Get('chart.text.size') + 2); + + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * Tooltips + */ + if (this.Get('chart.tooltips').length) { + + /** + * Register this object for redrawing + */ + RGraph.Register(this); + + /** + * The onclick event + */ + //this.canvas.onclick = function (e) + var canvas_onclick_func = function (e) + { + RGraph.HideZoomedCanvas(); + + e = RGraph.FixEventObject(e); + + var mouseCoords = RGraph.getMouseXY(e); + + var canvas = e.target; + var context = canvas.getContext('2d'); + var obj = e.target.__object__; + + + + /** + * If it's actually a donut make sure the hyp is bigger + * than the size of the hole in the middle + */ + if (obj.Get('chart.variant') == 'donut' && Math.abs(hyp) < (obj.radius / 2)) { + return; + } + + /** + * The angles for each segment are stored in "angles", + * so go through that checking if the mouse position corresponds + */ + var isDonut = obj.Get('chart.variant') == 'donut'; + var hStyle = obj.Get('chart.highlight.style'); + var segment = obj.getSegment(e); + + if (segment) { + + var x = mouseCoords[0] - segment[0]; + var y = mouseCoords[1] - segment[1]; + var theta = Math.atan(y / x); // RADIANS + var hyp = y / Math.sin(theta); + + + if ( RGraph.Registry.Get('chart.tooltip') + && segment[5] == RGraph.Registry.Get('chart.tooltip').__index__ + && RGraph.Registry.Get('chart.tooltip').__canvas__.__object__.id == obj.id) { + + return; + + } else { + RGraph.Redraw(); + } + + + if (isDonut || hStyle == '2d') { + + context.beginPath(); + + context.strokeStyle = obj.Get('chart.highlight.style.2d.stroke'); + context.fillStyle = obj.Get('chart.highlight.style.2d.fill'); + + //context.moveTo(obj.centerx, obj.centery); + + context.moveTo(segment[0], segment[1]); + context.arc(segment[0], segment[1], segment[2], RGraph.degrees2Radians(obj.angles[segment[5]][0]), RGraph.degrees2Radians(obj.angles[segment[5]][1]), 0); + context.lineTo(segment[0], segment[1]); + context.closePath(); + + context.stroke(); + context.fill(); + + //Removed 7th December 2010 + //context.stroke(); + + } else if (hStyle == 'explode') { + + var exploded = []; + + exploded[segment[5]] = 0; + + RGraph.Registry.Set('chart.pie.exploded', obj); + + 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); + 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); + 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); + 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); + 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); + + setTimeout(function () {RGraph.Registry.Get('chart.pie.exploded').Set('chart.exploded', []);}, 150); + + } else { + + context.lineWidth = 2; + + /** + * Draw a white segment where the one that has been clicked on was + */ + context.fillStyle = 'white'; + context.strokeStyle = 'white'; + context.beginPath(); + context.moveTo(segment[0], segment[1]); + context.arc(segment[0], segment[1], segment[2], obj.angles[segment[5]][0] / 57.3, obj.angles[segment[5]][1] / 57.3, 0); + context.stroke(); + context.fill(); + + context.lineWidth = 1; + + context.shadowColor = '#666'; + context.shadowBlur = 3; + context.shadowOffsetX = 3; + context.shadowOffsetY = 3; + + // Draw the new segment + context.beginPath(); + context.fillStyle = obj.Get('chart.colors')[segment[5]]; + context.strokeStyle = obj.Get('chart.strokestyle'); + context.moveTo(segment[0] - 3, segment[1] - 3); + 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); + context.lineTo(segment[0] - 3, segment[1] - 3); + context.closePath(); + + context.stroke(); + context.fill(); + + // Turn off the shadow + RGraph.NoShadow(obj); + + /** + * If a border is defined, redraw that + */ + if (obj.Get('chart.border')) { + context.beginPath(); + context.strokeStyle = obj.Get('chart.border.color'); + context.lineWidth = 5; + context.arc(segment[0] - 3, segment[1] - 3, obj.radius - 2, RGraph.degrees2Radians(obj.angles[i][0]), RGraph.degrees2Radians(obj.angles[i][1]), 0); + context.stroke(); + } + } + + /** + * If a tooltip is defined, show it + */ + + /** + * Get the tooltip text + */ + var text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), segment[5]); + + if (text) { + RGraph.Tooltip(canvas, text, e.pageX, e.pageY, segment[5]); + } + + /** + * Need to redraw the key? + */ + if (obj.Get('chart.key') && obj.Get('chart.key').length && obj.Get('chart.key.position') == 'graph') { + RGraph.DrawKey(obj, obj.Get('chart.key'), obj.Get('chart.colors')); + } + + e.stopPropagation(); + + return; + } else if (obj.Get('chart.tooltips.event') == 'onclick') { + RGraph.Redraw(); + } + } + var event_name = this.Get('chart.tooltips.event') == 'onmousemove' ? 'mousemove' : 'click'; + + this.canvas.addEventListener(event_name, canvas_onclick_func, false); + RGraph.AddEventListener(this.id, event_name, canvas_onclick_func); + + + + + + + /** + * The onmousemove event for changing the cursor + */ + //this.canvas.onmousemove = function (e) + var canvas_onmousemove_func = function (e) + { + RGraph.HideZoomedCanvas(); + + e = RGraph.FixEventObject(e); + + var obj = e.target.__object__; + var segment = obj.getSegment(e); + + if (segment) { + e.target.style.cursor = 'pointer'; + + return; + } + + /** + * Put the cursor back to null + */ + e.target.style.cursor = 'default'; + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + + + + + + + + + + /** + * The window onclick function + */ + var window_onclick_func = function (e) + { + // Taken out on 02/10/11 + //RGraph.HideZoomedCanvas(); + + e = RGraph.FixEventObject(e); + + RGraph.Redraw(); + + /** + * Put the cursor back to null + */ + //e.target.style.cursor = 'default'; + } + window.addEventListener('click', window_onclick_func, false); + RGraph.AddEventListener('window_' + this.id, 'click', window_onclick_func); + } + + + /** + * If a border is pecified, draw it + */ + if (this.Get('chart.border')) { + this.context.beginPath(); + this.context.lineWidth = 5; + this.context.strokeStyle = this.Get('chart.border.color'); + + this.context.arc(this.centerx, + this.centery, + this.radius - 2, + 0, + 6.28, + 0); + + this.context.stroke(); + } + + /** + * Draw the kay if desired + */ + if (this.Get('chart.key') != null) { + //this.Set('chart.key.position', 'graph'); + RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors')); + } + + + /** + * If this is actually a donut, draw a big circle in the middle + */ + if (this.Get('chart.variant') == 'donut') { + this.context.beginPath(); + this.context.strokeStyle = this.Get('chart.strokestyle'); + this.context.fillStyle = this.Get('chart.variant.donut.color'); + this.context.arc(this.centerx, this.centery, this.radius / 2, 0, 6.28, 0); + this.context.stroke(); + this.context.fill(); + } + + RGraph.NoShadow(this); + + /** + * 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); + } + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws a single segment of the pie chart + * + * @param int degrees The number of degrees for this segment + */ + RGraph.Pie.prototype.DrawSegment = function (degrees, color, last, index) + { + var context = this.context; + var canvas = this.canvas; + var subTotal = this.subTotal; + degrees = degrees * this.Get('chart.effect.roundrobin.multiplier'); + + context.beginPath(); + + context.fillStyle = color; + context.strokeStyle = this.Get('chart.strokestyle'); + context.lineWidth = 0; + + if (this.Get('chart.shadow')) { + RGraph.SetShadow(this, this.Get('chart.shadow.color'),this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur')); + } + + /** + * Exploded segments + */ + if ( (typeof(this.Get('chart.exploded')) == 'object' && this.Get('chart.exploded')[index] > 0) || typeof(this.Get('chart.exploded')) == 'number') { + var explosion = typeof(this.Get('chart.exploded')) == 'number' ? this.Get('chart.exploded') : this.Get('chart.exploded')[index]; + var x = 0; + var y = 0; + var h = explosion; + var t = ((subTotal + (degrees / 2)) / (360/6.2830)) - 1.57; + var x = (Math.cos(t) * explosion); + var y = (Math.sin(t) * explosion); + + this.context.moveTo(this.centerx + x, this.centery + y); + } else { + var x = 0; + var y = 0; + } + + /** + * Calculate the angles + */ + var startAngle = ((subTotal / 57.3)) - 1.57; + var endAngle = (((subTotal + degrees) / 57.3)) - 1.57; + + context.arc(this.centerx + x, + this.centery + y, + this.radius, + startAngle, + endAngle, + 0); + + context.lineTo(this.centerx + x, this.centery + y); + + // Keep hold of the angles + this.angles.push([subTotal - 90, subTotal + degrees - 90, this.centerx + x, this.centery + y]) + this.context.closePath(); + + + + //this.context.stroke(); + this.context.fill(); + + /** + * Calculate the segment angle + */ + this.Get('chart.segments').push([subTotal, subTotal + degrees]); + this.subTotal += degrees; + } + + /** + * Draws the graphs labels + */ + RGraph.Pie.prototype.DrawLabels = function () + { + var hAlignment = 'left'; + var vAlignment = 'center'; + var labels = this.Get('chart.labels'); + var context = this.context; + + /** + * Turn the shadow off + */ + RGraph.NoShadow(this); + + context.fillStyle = 'black'; + context.beginPath(); + + /** + * Draw the key (ie. the labels) + */ + if (labels && labels.length) { + + var text_size = this.Get('chart.text.size'); + + for (i=0; i<labels.length; ++i) { + + /** + * T|his ensures that if we're given too many labels, that we don't get an error + */ + if (typeof(this.Get('chart.segments')[i]) == 'undefined') { + continue; + } + + // Move to the centre + context.moveTo(this.centerx,this.centery); + + var a = this.Get('chart.segments')[i][0] + ((this.Get('chart.segments')[i][1] - this.Get('chart.segments')[i][0]) / 2) - 90; + + /** + * Alignment + */ + if (a < 90) { + hAlignment = 'left'; + vAlignment = 'center'; + } else if (a < 180) { + hAlignment = 'right'; + vAlignment = 'center'; + } else if (a < 270) { + hAlignment = 'right'; + vAlignment = 'center'; + } else if (a < 360) { + hAlignment = 'left'; + vAlignment = 'center'; + } + +var angle = ((this.angles[i][1] - this.angles[i][0]) / 2) + this.angles[i][0]; + /** + * Handle the additional "explosion" offset + */ + if (typeof(this.Get('chart.exploded')) == 'object' && this.Get('chart.exploded')[i] || typeof(this.Get('chart.exploded')) == 'number') { + + var t = ((this.angles[i][1] - this.angles[i][0]) / 2) / (360/6.2830); + var seperation = typeof(this.Get('chart.exploded')) == 'number' ? this.Get('chart.exploded') : this.Get('chart.exploded')[i]; + + // Adjust the angles + var explosion_offsetx = (Math.cos(angle / 57.29) * seperation); + var explosion_offsety = (Math.sin(angle / 57.29) * seperation); + } else { + var explosion_offsetx = 0; + var explosion_offsety = 0; + } + + /** + * Allow for the label sticks + */ + if (this.Get('chart.labels.sticks')) { + explosion_offsetx += (Math.cos(angle / 57.29) * this.Get('chart.labels.sticks.length')); + explosion_offsety += (Math.sin(angle / 57.29) * this.Get('chart.labels.sticks.length')); + } + + + context.fillStyle = this.Get('chart.text.color'); + + RGraph.Text(context, + this.Get('chart.text.font'), + text_size, + this.centerx + explosion_offsetx + ((this.radius + 10)* Math.cos(a / 57.3)) + (this.Get('chart.labels.sticks') ? (a < 90 || a > 270 ? 2 : -2) : 0), + this.centery + explosion_offsety + (((this.radius + 10) * Math.sin(a / 57.3))), + labels[i], + vAlignment, + hAlignment); + } + + context.fill(); + } + } + + + /** + * This function draws the pie chart sticks (for the labels) + */ + RGraph.Pie.prototype.DrawSticks = function () + { + var context = this.context; + var offset = this.Get('chart.linewidth') / 2; + var exploded = this.Get('chart.exploded'); + var sticks = this.Get('chart.labels.sticks'); + + for (var i=0; i<this.angles.length; ++i) { + + // This allows the chart.labels.sticks to be an array as well as a boolean + if (typeof(sticks) == 'object' && !sticks[i]) { + continue; + } + + var degrees = this.angles[i][1] - this.angles[i][0]; + + context.beginPath(); + context.strokeStyle = this.Get('chart.labels.sticks.color'); + context.lineWidth = 1; + + var midpoint = (this.angles[i][0] + (degrees / 2)) / 57.3; + + if (typeof(exploded) == 'object' && exploded[i]) { + var extra = exploded[i]; + } else if (typeof(exploded) == 'number') { + var extra = exploded; + } else { + var extra = 0; + } + + context.lineJoin = 'round'; + context.lineWidth = 1; + + context.arc(this.centerx, + this.centery, + this.radius + this.Get('chart.labels.sticks.length') + extra, + midpoint, + midpoint + 0.001, + 0); + context.arc(this.centerx, + this.centery, + this.radius + extra, + midpoint, + midpoint + 0.001, + 0); + + context.stroke(); + } + } + + + /** + * The (now Pie chart specific) getSegment function + * + * @param object e The event object + */ + RGraph.Pie.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 r = obj.radius; + var angles = obj.angles; + var ret = []; + + for (var i=0; i<angles.length; ++i) { + + var x = mouseCoords[0] - angles[i][2]; + var y = mouseCoords[1] - angles[i][3]; + var theta = Math.atan(y / x); // RADIANS + var hyp = y / Math.sin(theta); + var hyp = (hyp < 0) ? hyp + accuracy : hyp - accuracy; + // Put theta in DEGREES + theta *= 57.3 + + /** + * Account for the correct quadrant + */ + if (x < 0 && y >= 0) { + theta += 180; + } else if (x < 0 && y < 0) { + theta += 180; + } + + if (theta > 360) { + theta -= 360; + } + + if (theta >= angles[i][0] && theta < angles[i][1]) { + + hyp = Math.abs(hyp); + + if (!hyp || (obj.radius && hyp > obj.radius) ) { + return null; + } + + if (obj.type == 'pie' && obj.Get('chart.variant') == 'donut' && (hyp > obj.radius || hyp < (obj.radius / 2) ) ) { + return null; + } + + ret[0] = angles[i][2]; + ret[1] = angles[i][3]; + ret[2] = (obj.type == 'rose') ? angles[i][2] : obj.radius; + ret[3] = angles[i][0]; + ret[4] = angles[i][1]; + ret[5] = i; + + + + if (ret[3] < 0) ret[3] += 360; + if (ret[4] > 360) ret[4] -= 360; + + return ret; + } + } + + return null; + } + + + RGraph.Pie.prototype.DrawBorders = function () + { + if (this.Get('chart.linewidth') > 0) { + + this.context.lineWidth = this.Get('chart.linewidth'); + this.context.strokeStyle = this.Get('chart.strokestyle'); + + for (var i=0,len=this.angles.length; i<len; ++i) { + this.context.beginPath(); + this.context.moveTo(this.angles[i][2], this.angles[i][3]); + 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); + 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); + this.context.closePath(); + + this.context.stroke(); + } + } + } + + + /** + * Returns the radius of the pie chart + */ + RGraph.Pie.prototype.getRadius = function () + { + return Math.min(this.canvas.height - this.gutterTop - this.gutterBottom, this.canvas.width - this.gutterLeft - this.gutterRight) / 2; + } + + + /** + * A programmatic explode function + * + * @param object obj The chart object + * @param number index The zero-indexed number of the segment + * @param number size The size (in pixels) of the explosion + */ + RGraph.Pie.prototype.Explode = function (index, size) + { + if (this.Get('chart.exploded') == 0) { + this.Set('chart.exploded', []); + } + + var obj = this; + + for (var i=0; i<size; ++i) { + setTimeout( + function () + { + var exploded = obj.Get('chart.exploded'); + var value = typeof(exploded[index]) == 'number' ? exploded[index] : 0; + exploded[index] = value + 1; + obj.Set('chart.exploded', exploded); + RGraph.Clear(obj.canvas); + obj.Draw(); + }, i * 16.666); + } + + /** + * Now set the property accordingly + */ + setTimeout( + function () + { + obj.Set('chart.exploded', exploded); + }, i * 16.666 + ) + + //var Reset = function () + //{ + // pie.Set('chart.exploded', []); + // RGraph.Clear(pie.canvas); + // pie.Draw(); + //} + //window.addEventListener('click', Reset, false); + }
\ No newline at end of file |