/** * Copyright (c) 2009 Chris Leonello * jqPlot is currently available for use in all personal or commercial projects * under both the MIT and GPL version 2.0 licenses. This means that you can * choose the license that best suits your project and use it accordingly. * * The author would appreciate an email letting him know of any substantial * use of jqPlot. You can reach the author at: chris dot leonello at gmail * dot com or see http://www.jqplot.com/info.php . This is, of course, * not required. * * If you are feeling kind and generous, consider supporting the project by * making a donation at: http://www.jqplot.com/donate.php . * * Thanks for using jqPlot! * */ (function($) { /** * Class: $.jqplot.PieRenderer * Plugin renderer to draw a pie chart. * Pie charts will draw only the first series. Other series are ignored. * x values, if present, will be used as slice labels. * y values give slice size. */ $.jqplot.PieRenderer = function(){ $.jqplot.LineRenderer.call(this); }; $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer(); $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer; // called with scope of a series $.jqplot.PieRenderer.prototype.init = function(options) { // Group: Properties // // prop: diameter // diameter of the pie, auto computed by default this.diameter = null; // prop: padding // padding between the pie and plot edges, legend, etc. this.padding = 20; // prop: sliceMargin // pixels spacing between pie slices. this.sliceMargin = 0; // prop: fill // true or false, wether to fil the slices. this.fill = true; // prop: shadowOffset // offset of the shadow from the slice and offset of // each succesive stroke of the shadow from the last. this.shadowOffset = 2; // prop: shadowAlpha // transparency of the shadow (0 = transparent, 1 = opaque) this.shadowAlpha = 0.07; // prop: shadowDepth // number of strokes to apply to the shadow, // each stroke offset shadowOffset from the last. this.shadowDepth = 5; this.tickRenderer = $.jqplot.PieTickRenderer; $.extend(true, this, options); if (this.diameter != null) { this.diameter = this.diameter - this.sliceMargin; } this._diameter = null; }; $.jqplot.PieRenderer.prototype.setGridData = function(plot) { // this is a no-op }; $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) { var stack = []; var td = []; for (var i=0; i0) { stack[i] += stack[i-1]; } } var fact = Math.PI*2/stack[stack.length - 1]; for (var i=0; i 6.282) { ang2 = 6.282; if (ang1 > ang2) { ang1 = 6.281; } } ctx.beginPath(); ctx.moveTo(0, 0); ctx.fillStyle = color; ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.arc(0, 0, r, ang1, ang2, false); ctx.closePath(); if (fill) { ctx.fill(); } else { ctx.stroke(); } } if (isShadow) { for (var i=0; i= 4.712 || mid_ang <= 1.57) ? 6 : -6; var line2_end_x = line1_end_x + line2_end_x_offset; var line2_end_y = line1_end_y; ctx.lineTo(line2_end_x, line2_end_y); ctx.stroke(); ctx.closePath(); // label var l = $("
"+gd[i][0]+" "+percentage+"%
").insertAfter(ctx.canvas); var l_x_offset = (mid_ang >= 4.712 || mid_ang <= 1.57) ? 4 : -1 * l.width() - 4; var l_y_offset = -1 * l.height() / 2; var l_x = line2_end_x + origin.x + l_x_offset; var l_y = line2_end_y + origin.y + l_y_offset; l.css({left: l_x+"px", top: l_y+"px"}); // console.log(gd[i][0]+':'); // console.log(' mid_ang: '+mid_ang); // console.log(' l_x_offset: '+l_x_offset); // console.log(' l_y_offset: '+l_y_offset); // console.log(' l_x: '+l_x); // console.log(' l_y: '+l_y); // console.log(' line1_start_x: '+line1_start_x); // console.log(' line1_start_y: '+line1_start_y); // console.log(' line1_end_x: '+line1_end_x); // console.log(' line1_end_y: '+line1_end_y); // console.log(' line2_end_x_offset: '+line2_end_x_offset); // console.log(' line2_end_x: '+line2_end_x); // console.log(' line2_end_y: '+line2_end_y); } } ctx.restore(); }; $.jqplot.PieAxisRenderer = function() { $.jqplot.LinearAxisRenderer.call(this); }; $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer; // There are no traditional axes on a pie chart. We just need to provide // dummy objects with properties so the plot will render. // called with scope of axis object. $.jqplot.PieAxisRenderer.prototype.init = function(options){ // this.tickRenderer = $.jqplot.PieTickRenderer; $.extend(true, this, options); // I don't think I'm going to need _dataBounds here. // have to go Axis scaling in a way to fit chart onto plot area // and provide u2p and p2u functionality for mouse cursor, etc. // for convienence set _dataBounds to 0 and 100 and // set min/max to 0 and 100. this._dataBounds = {min:0, max:100}; this.min = 0; this.max = 100; this.showTicks = false; this.ticks = []; this.showMark = false; this.show = false; }; $.jqplot.PieLegendRenderer = function() { $.jqplot.TableLegendRenderer.call(this); }; $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer; // called with context of legend $.jqplot.PieLegendRenderer.prototype.draw = function() { var legend = this; if (this.show) { var series = this._series; // make a table. one line label per row. var ss = 'position:absolute;'; ss += (this.background) ? 'background:'+this.background+';' : ''; ss += (this.border) ? 'border:'+this.border+';' : ''; ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : ''; ss += (this.textColor) ? 'color:'+this.textColor+';' : ''; this._elem = $('
'); var pad = false; var s = series[0]; var colorGenerator = new s.colorGenerator(s.seriesColors); if (s.show) { var pd = s.data; for (var i=0; i