/** * ----------------------------------------------------------------------------- * file: CanvasDraw.ui.drawingGraph.js * file version: 1.0.0 * date: 2011-10-17 * * A jQuery plugin provided by the piwigo's plugin "GrumPluginClasses" * * ----------------------------------------------------------------------------- * Author : Grum * email : grum@piwigo.com * website : http://photos.grum.fr * PWG user : http://forum.phpwebgallery.net/profile.php?id=3706 * * << May the Little SpaceFrog be with you ! >> * ----------------------------------------------------------------------------- * * The drawing graph provide all methods and properties to draw charts * * It use: * - 1 layer for graphs * - 1 layer for the grid & axis * - 1 layer for the cursor * * :: HISTORY :: * * | release | date | * | 1.0.0 | 2011-10-17 | first release * | | | * | | | * | | | * | | | * | | | * | | | * */ ( function($) { /* * plugin 'public' functions */ var publicMethods = { /** * initialize the object * * @param Object opt : options */ init : function (opt) { return this.each(function() { // default values for the plugin var $this=$(this), data = $this.data('options'), objects = $this.data('objects'), properties = $this.data('properties'), canvasObjects = $this.data('canvasObjects'), options = { margins:new CDMargins(), legend:new CDLegend(), axis:{ front:new CDAxis(), back:null }, cursor: { visible:true, color:'rgba(128,128,128,0.2)', verticalType:'bar' // 'bar' or 'line' }, display: { width:320, height:200, legend:false, }, events: { mousePositionChange:null, mouseEnter:null, mouseLeave:null, mouseClick:null }, }; // if options given, merge it // if(opt) $.extend(options, opt); ==> options are set by setters $this.data('options', options); if(!properties) { $this.data('properties', { initialized:false, mouseIsOver:false, cursor:{ x:0, y:0, axis:{ XY:{ front:{H:-1, V:-1}, back:{H:-1, V:-1} } }, }, typeGraph:'xy', // 'xy', 'pie' } ); properties=$this.data('properties'); } if(!objects) { objects = { viewport:$('
', { 'class':'ui-drawingGraph-viewport' } ), sheet:$('
', { 'class':'ui-drawingGraph-sheet' } ) .bind('mousemove', function (event) { privateMethods.mousePositionUpdate($this, event.originalEvent.layerX, event.originalEvent.layerY); } ) .bind('mouseleave', function (event) { privateMethods.mouseLeave($this); } ) .bind('mouseenter', function (event) { privateMethods.mouseEnter($this, event.originalEvent.layerX, event.originalEvent.layerY); } ) .bind('click', function (event) { privateMethods.mouseClick($this, event.originalEvent.layerX, event.originalEvent.layerY); } ), canvasCursor:$('', { 'class':'ui-drawingGraph-cursor' } ), canvasAxis:$('', { 'class':'ui-drawingGraph-axis' } ), canvasGraph:$('', { 'class':'ui-drawingGraph-graph' } ) }; canvasObjects = { cursor:new CDDrawing(objects.canvasCursor.get(0)), axis:new CDDrawing(objects.canvasAxis.get(0)), graph:new CDDrawing(objects.canvasGraph.get(0)), }; $this .html('') .addClass('ui-drawingGraph') .bind('click.drawingGraph', function () { // } ) .bind('mouseenter.drawingGraph', function () { properties.mouseIsOver=true; } ) .bind('mouseleave.drawingGraph', function () { properties.mouseIsOver=false; } ) .append(objects.viewport.append(objects.sheet.append(objects.canvasAxis).append(objects.canvasCursor).append(objects.canvasGraph))); $this.data('objects', objects); $this.data('canvasObjects', canvasObjects); } privateMethods.setOptions($this, opt); } ); }, // init /** * object destroy methods to clean memory */ destroy : function () { return this.each( function() { // default values for the plugin var $this=$(this); $this .unbind('.drawingGraph') .css( { width:'', height:'' } ); } ); }, // destroy /** * initialize the options * * @param Object value : options properties as an object */ options: function (value) { return this.each(function() { privateMethods.setOptions($(this), value); } ); }, // options /** * define the size (witdh & height) of the current drawing area * * @param Object value : an object with width&height properties * @return Object : if no parameter are given, returns an object with the * width & height properties */ display : function (value) { if(value!=null) { // set selected value return this.each(function() { privateMethods.setDisplay($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.display); } else { return(null); } } }, /** * define the cursor state * * @param Object value : an object with the cursor properties (visible, * color) * @return Object : if no parameter are given, returns an object with the * cursor properties */ cursor : function (value) { if(value!=null) { // set selected value return this.each(function() { privateMethods.setCursor($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.cursor); } else { return(null); } } }, /** * define the margins * * @param Object value : a CDMargins object or an object with left, top, right, bottom properties * @return Object : if no parameter are given, returns a CDMargins object */ margins : function (value) { if(value!=null && value instanceof CDMargins) { // set selected value return this.each(function() { privateMethods.setMargins($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.margins); } else { return(null); } } }, /** * define the legend * * @param Object value : a CDLegend object or an object with left, top, right, bottom properties * @return Object : if no parameter are given, returns a CDLegend object */ legend : function (value) { if(value!=null && value instanceof CDLegend) { // set selected value return this.each(function() { privateMethods.setLegend($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.legend); } else { return(null); } } }, /** * define the front axis * * @param Object value : a CDAxis object * @return Object : if no parameter are given, returns a CDAxis object */ axisFront : function (value) { if(value!=null && value instanceof CDAxis) { // set selected value return this.each(function() { privateMethods.setAxis($(this), value, true); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.axis.front); } else { return(null); } } }, /** * define the back axis * * @param Object value : a CDAxis object * @return Object : if no parameter are given, returns a CDAxis object */ axisBack : function (value) { if(value!=null && value instanceof CDAxis) { // set selected value return this.each(function() { privateMethods.setAxis($(this), value, false); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.axis.back); } else { return(null); } } }, /** * return the canvas objects * * @return Object : an object with axis, graph and cursor canvas */ canvasObjects : function () { var canvasObjects=this.data('canvasObjects'); if(canvasObjects) { return(canvasObjects); } else { return( { cursor:null, axis:null, graph:null } ); } }, /** * define the function to be triggered when the mouse moves on the drawing * area * * @param Function value : a function to be triggered * @return Function : if no paramater is given, return the function */ mousePositionChange: function (value) { if(value!=null && $.isFunction(value)) { // set selected value return this.each(function() { privateMethods.setEventMousePositionChange($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.events.mousePositionChange); } else { return(null); } } }, // mousePositionChange /** * define the function to be triggered when the mouse enter on the drawing * area * * @param Function value : a function to be triggered * @return Function : if no paramater is given, return the function */ mouseEnter: function (value) { if(value!=null && $.isFunction(value)) { // set selected value return this.each(function() { privateMethods.setEventMouseEnter($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.events.mouseEnter); } else { return(null); } } }, // mouseEnter /** * define the function to be triggered when the mouse leaves the drawing * area * * @param Function value : a function to be triggered * @return Function : if no paramater is given, return the function */ mouseLeave: function (value) { if(value!=null && $.isFunction(value)) { // set selected value return this.each(function() { privateMethods.setEventMouseLeave($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.events.mouseLeave); } else { return(null); } } }, // mouseLeave /** * define the function to be triggered when the mouse is clicked on the * drawing area * * @param Function value : a function to be triggered * @return Function : if no paramater is given, return the function */ mouseClick: function (value) { if(value!=null && $.isFunction(value)) { // set selected value return this.each(function() { privateMethods.setEventMouseClick($(this), value); } ); } else { // return the selected value var options=this.data('options'); if(options) { return(options.events.mouseClick); } else { return(null); } } }, // mouseClick /** * force the drawing area to refresh display */ refresh: function () { return this.each(function() { privateMethods.draw($(this)); } ); } }, // methods /* * plugin 'private' methods */ privateMethods = { /** * initialise the object with given options * * @param object value: options to be set */ setOptions : function (object, value) { var properties=object.data('properties'), options=object.data('options'); if(!$.isPlainObject(value)) return(false); properties.initialized=false; if(value.axis==null) value.axis={}; if(value.events==null) value.events={}; privateMethods.setMargins(object, (value.margins!=null)?value.margins:options.margins); privateMethods.setLegend(object, (value.legend!=null)?value.legend:options.legend); privateMethods.setCursor(object, (value.cursor!=null)?value.cursor:options.cursor); privateMethods.setAxis(object, (value.axis.front!=null)?value.axis.front:options.axis.front, true); privateMethods.setAxis(object, (value.axis.back!=null)?value.axis.back:options.axis.back, false); privateMethods.setDisplay(object, (value.display!=null)?value.display:options.display); privateMethods.setEventMousePositionChange(object, (value.events.mousePositionChange!=null)?value.events.mousePositionChange:options.events.mousePositionChange); privateMethods.setEventMouseLeave(object, (value.events.mouseLeave!=null)?value.events.mouseLeave:options.events.mouseLeave); privateMethods.setEventMouseEnter(object, (value.events.mouseEnter!=null)?value.events.mouseEnter:options.events.mouseEnter); privateMethods.setEventMouseClick(object, (value.events.mouseClick!=null)?value.events.mouseClick:options.events.mouseClick); properties.initialized=true; privateMethods.draw(object); }, /** * setDisplay allows to resize the sheetSizeport * * @param object value: an object with width&height properties * @return object: display options properties */ setDisplay : function (object, value) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'), canvasObjects=object.data('canvasObjects'), triggerSize=false, axisBox={ width:0, height:0 }; if(value.width==null) value.width=options.display.width; if(value.height==null) value.height=options.display.height; if(value.width>0 && value.height>0 && (value.width!=options.display.width || value.height!=options.display.height || !properties.initialized) ) { delete canvasObjects.cursor; delete canvasObjects.axis; delete canvasObjects.graph; options.display.width=value.width; options.display.height=value.height; objects.sheet.css( { width:options.display.width+'px', height:options.display.height+'px' } ); objects.viewport.attr("height", options.display.height).attr("width", options.display.width); objects.canvasCursor.attr("height", options.display.height).attr("width", options.display.width); objects.canvasAxis.attr("height", options.display.height).attr("width", options.display.width); objects.canvasGraph.attr("height", options.display.height).attr("width", options.display.width); object.attr("height", options.display.height).attr("width", options.display.width); object.css( { width:options.display.width+'px', height:options.display.height+'px' } );//attr("height", options.display.height).attr("width", options.display.width); canvasObjects.cursor=new CDDrawing(objects.canvasCursor.get(0)); canvasObjects.axis=new CDDrawing(objects.canvasAxis.get(0)); canvasObjects.graph=new CDDrawing(objects.canvasGraph.get(0)); axisBox=privateMethods.axisBox(object); if(options.axis.front!=null) options.axis.front.set( { size:{ width:axisBox.width, //options.display.width-options.margins.get().left-options.margins.get().right, height:axisBox.height //options.display.height-options.margins.get().top-options.margins.get().bottom } } ); if(options.axis.back!=null) options.axis.back.set( { size:{ width:axisBox.width, //options.display.width-options.margins.get().left-options.margins.get().right, height:axisBox.height //options.display.height-options.margins.get().top-options.margins.get().bottom } } ); if(properties.initialized) { /* * redraw graph */ } } return(options.display); }, // setDisplay /** * define the cursor properties * * @param object value: the cursor properties (color, visible, verticalType) * @return object: cursor options values */ setCursor : function (object, value) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'), redraw=false; if(value.color==null) value.color=options.cursor.color; if(value.visible==null) value.visible=options.cursor.visible; if(value.verticalType==null) value.verticalType=options.cursor.verticalType; if((value.visible===true || value.visible===false) && (value.verticalType=='bar' || value.verticalType=='line') && (value.visible!=options.cursor.visible || value.color!=options.cursor.color || value.verticalType!=options.cursor.verticalType || !properties.initialized) ) { if(options.cursor.color!=value.color || options.cursor.verticalType!=value.verticalType || options.cursor.visible!=value.visible) redraw=true; options.cursor.visible=value.visible; options.cursor.color=value.color; options.cursor.verticalType=value.verticalType; objects.canvasCursor.css('display', options.cursor.visible?'block':'none'); if(options.cursor.visible && redraw) privateMethods.drawCursor(object); } return(options.cursor); }, // setCursor /** * define the margins * * @param CDMargins value: a CDMargins object * @return CDMargins: the CDMargins applied */ setMargins : function (object, value) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'); if(value instanceof CDMargins && (!options.margins.equals(value) || !properties.initialized) ) { options.margins.set(value); privateMethods.draw(object); } return(options.margins); }, // setMargins /** * define the legend * * @param CDLegend value: a CDLegend object * @return CDLegend: current CDLegend applied */ setLegend : function (object, value) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'); if(value instanceof CDLegend && (!options.legend.equals(value) || !properties.initialized) ) { options.legend.set(value); privateMethods.draw(object); } return(options.legend); }, // setLegend /** * define the axis * * @param CDAxis value: a CDAxis object * @param boolean front: true if function is called to define the front axis, * false if function is called to define the baxk axis * @return CDAxis: the CDAxis object applied */ setAxis : function (object, value, front) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'); if(value instanceof CDAxis) { if(front) { delete options.axis.front; options.axis.front=value; } else { delete options.axis.back; options.axis.back=value; } privateMethods.draw(object); } return(front?options.axis.front:options.axis.back); }, // setAxis /** * this function is used to set a callback when mouse position changed over * the viewport */ setEventMousePositionChange : function (object, value) { var properties=object.data('properties'), options=object.data('options'); options.events.mousePositionChange=value; object.unbind('drawingGraphMousePositionChange'); if(value) object.bind('drawingGraphMousePositionChange', options.events.mousePositionChange); return(options.events.mousePositionChange); }, //setEventMousePositionChange /** * this function is used to set a callback when mouse leave the viewport */ setEventMouseLeave : function (object, value) { var properties=object.data('properties'), options=object.data('options'); options.events.mouseLeave=value; object.unbind('drawingGraphMouseLeave'); if(value) object.bind('drawingGraphMouseLeave', options.events.mouseLeave); return(options.events.mouseLeave); }, //setEventMouseLeave /** * this function is used to set a callback when mouse enter the viewport */ setEventMouseEnter : function (object, value) { var properties=object.data('properties'), options=object.data('options'); options.events.mouseEnter=value; object.unbind('drawingGraphMouseEnter'); if(value) object.bind('drawingGraphMouseEnter', options.events.mouseEnter); return(options.events.mouseEnter); }, //setEventMouseEnter /** * this function is used to set a callback when mouse is clicked on the * viewport */ setEventMouseClick : function (object, value) { var properties=object.data('properties'), options=object.data('options'); options.events.mouseClick=value; object.unbind('drawingGraphMouseClick'); if(value) object.bind('drawingGraphMouseClick', options.events.mouseClick); return(options.events.mouseClick); }, // setEventMouseClick /** * this function is called when the mouse moves on the drawing area * - calculate the axis position * - draw cursor * - trigger function event if any * * Note: works only if the axis mode is 'XY'. * * @param integer valueX: x position on the canvas * @param integer valueY: y position on the canvas */ mousePositionUpdate : function (object, valueX, valueY) { var properties=object.data('properties'), options=object.data('options'), work={ margins:options.margins.get(), legend:options.legend.get(), axis:{ front:(options.axis.front!=null)?options.axis.front.get():null, back:(options.axis.back!=null)?options.axis.back.get():null }, values:[], axisValues:{}, axisPos:{ x:0, y:0 }, updated:false }, /** * returns for each series, the value associated with the cursor's position * * @param Array series: series * @param integer position: horinzontal cursor position * @return Array: array of series values */ calculateSeriesValues = function (series, position) { var tmpSerie=null, returned=[]; for(var i=0;i=0 && position0) object.trigger('drawingGraphMousePositionChange', { position:{ x:properties.cursor.x, y:properties.cursor.y }, values:work.values } ); }, // mousePositionUpdate /** * this function is called when the mouse moves on the drawing area * - hide cursor * - trigger function event if any */ mouseLeave : function (object) { var objects=object.data('objects'), options=object.data('options'), properties=object.data('properties'); objects.canvasCursor.css('display', 'none'); properties.cursor.axis.XY.front.H=-1; properties.cursor.axis.XY.front.V=-1; properties.cursor.axis.XY.back.H=-1; properties.cursor.axis.XY.back.V=-1; if(options.events.mouseLeave) object.trigger('drawingGraphMouseLeave'); }, /** * this function is called when the mouse moves on the drawing area * - show cursor * - trigger function event if any */ mouseEnter : function (object) { var objects=object.data('objects'), options=object.data('options'); objects.canvasCursor.css('display', options.cursor.visible?'block':'none'); if(options.events.mouseEnter) object.trigger('drawingGraphMouseEnter'); }, /** * this function is called when the mouse click on the drawing area */ mouseClick : function (object) { var options=object.data('options'); if(options.events.mouseClick) object.trigger('drawingGraphMouseClick'); }, /** * return position relative to the axis * * @param integer x: x position * @param integer y: y position * @return object: a {x,y} object; coordinates relative to the axis */ axisXYRelativePosition : function (object, x, y) { var properties=object.data('properties'), options=object.data('options'), work={ margins:options.margins.get(), legend:options.legend.get(), returned:{ x:0, y:0 } }; work.returned.y=options.display.height-y-work.margins.bottom; work.returned.x=x-work.margins.left; if(work.legend.visible && work.legend.position=='left') work.returned.x-=options.legend.getRealWidth()+work.margins.right; return(work.returned); }, //axisXYRelativePosition /** * calculate the axis box * * @return object: axis dimensions */ axisBox : function (object) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'), work={ margins:options.margins.get(), legend:options.legend.get(), returned:{ width:0, height:0 } }; work.returned.height=options.display.height-options.margins.get().top-options.margins.get().bottom; work.returned.width=options.display.width-options.margins.get().left-options.margins.get().right; if(work.legend.visible) work.returned.width-=options.legend.getRealWidth()+options.margins.get().right; return(work.returned); }, /** * this function draws the cursor */ drawCursor : function (object) { var properties=object.data('properties'), objects=object.data('objects'), options=object.data('options'), canvasObjects=object.data('canvasObjects'), work={ margins:options.margins.get(), axis:{ front:(options.axis.front!=null)?options.axis.front.get():null, back:(options.axis.back!=null)?options.axis.back.get():null }, width:options.display.width, height:options.display.height, nearest:0, step:0, axisValues: { front:{H:0, V:0}, back:{H:0, V:0} } }; // draw the cursor only if at least, one of the axis mode equals XY if(!(work.axis.front!=null && work.axis.front.properties.mode=='XY' || work.axis.back!=null && work.axis.back.properties.mode=='XY')) return(false); // prepare canvas area canvasObjects.cursor.drawingManageCrisp(true); canvasObjects.cursor.shapeClearRect(0,0,work.width, work.height); canvasObjects.cursor.styleStrokeColor(options.cursor.color); canvasObjects.cursor.styleFillColor(options.cursor.color); canvasObjects.cursor.styleStrokeDraw({width:1, cap:'butt', joints:'miter'}); //save canvas state canvasObjects.cursor.drawingStatePush(); // get relative position to the axis work.axisPos=privateMethods.axisXYRelativePosition(object, 0, 0); // flip canvas vertically & translate (zero in vertical position is localized at the bottom) canvasObjects.cursor.transformScale({y:-1}); canvasObjects.cursor.transformTranslate( { x:-work.axisPos.x, y:-work.axisPos.y } ); // front axis managment if(work.axis.front!=null && work.axis.front.properties.mode=='XY' && (work.axis.front.properties.display.visible.XY.cursorH || work.axis.front.properties.display.visible.XY.cursorV) ) { if(work.axis.front.properties.display.visible.XY.cursorH && properties.cursor.axis.XY.front.H>=0 && properties.cursor.axis.XY.front.H=0 && work.nearest<=work.axis.front.properties.size.height ) { // draw the value line canvasObjects.cursor.shapeLine(0, work.nearest, work.axis.front.properties.size.width, work.nearest); } } // front axis managment // back axis managment if(work.axis.back!=null && work.axis.back.properties.mode=='XY' && (work.axis.back.properties.display.visible.XY.cursorH || work.axis.back.properties.display.visible.XY.cursorV) ) { if(work.axis.back.properties.display.visible.XY.cursorH && properties.cursor.axis.XY.back.H>=0 && properties.cursor.axis.XY.back.H=0 && work.nearest<=work.axis.back.properties.size.height) { canvasObjects.cursor.shapeLine(0, work.nearest, work.axis.back.properties.size.width, work.nearest); } } // back axis managment //restore the canvas state canvasObjects.cursor.drawingStatePop(); }, //drawCursor /** * this function draws the graphs */ draw : function (object) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ margins:options.margins.get(), axis:{ front:(options.axis.front!=null)?options.axis.front.get():null, back:(options.axis.back!=null)?options.axis.back.get():null }, width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight(), legendBox:null }; if(!properties.initialized) return(false); canvasObjects.axis.shapeClearRect(0,0,work.width, work.height); canvasObjects.graph.shapeClearRect(0,0,work.width, work.height); canvasObjects.axis.drawingManageCrisp(true); canvasObjects.graph.drawingManageCrisp(true); canvasObjects.axis.drawingStatePush(); canvasObjects.graph.drawingStatePush(); canvasObjects.axis.transformScale({y:-1}); canvasObjects.graph.transformScale({y:-1}); canvasObjects.axis.transformTranslate({x:work.margins.left, y:work.margins.bottom-work.height}); canvasObjects.graph.transformTranslate({x:work.margins.left, y:work.margins.bottom-work.height}); privateMethods.drawLegend(object); if(work.axis.back!=null) privateMethods.drawGraph(object, options.axis.back); if(work.axis.front!=null) privateMethods.drawGraph(object, options.axis.front); canvasObjects.axis.drawingStatePop(); canvasObjects.graph.drawingStatePop(); return(true); }, drawGraph : function (object, axis) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ axis:axis.get(), margins:options.margins.get(), width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight() }; privateMethods.drawAxis(object, axis); for(var i=work.axis.properties.series.length-1;i>=0;i--) { switch(work.axis.properties.series[i].get().options.get().type) { case 'bar': privateMethods.drawSerieBar(object, axis, work.axis.properties.series[i]); break; case 'area': privateMethods.drawSerieArea(object, axis, work.axis.properties.series[i]); break; case 'line': privateMethods.drawSerieLine(object, axis, work.axis.properties.series[i]); break; case 'pie': privateMethods.drawSeriePie(object, axis, work.axis.properties.series[i]); break; } } }, /** * draw the axis; canvas must be ready before calling this function */ drawAxis : function (object, axis) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ margins:options.margins.get(), axis:axis.get(), width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight() }; if( work.axis.properties.mode=='pie' && !work.axis.properties.display.visible.pie || work.axis.properties.mode=='XY' && !work.axis.properties.display.visible.XY.H && !work.axis.properties.display.visible.XY.V ) return(false); // prepare canvas canvasObjects.axis.styleFillColor(work.axis.properties.display.color); canvasObjects.axis.styleStrokeColor(work.axis.properties.display.color); canvasObjects.axis.styleStrokeDraw({width:1, cap:'butt', joints:'miter'}); /* * ------------------------------------------------------------------- * drawing horizontal ticks&values * ------------------------------------------------------------------- */ if(work.axis.properties.mode=='XY' && work.axis.properties.display.visible.XY.H) { canvasObjects.axis.shapeLine(0,0,work.axis.properties.size.width,0); // prepare values switch(work.axis.properties.XY.ticks.H.value.rotate) { case 0: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.H.value.fontName+' '+work.axis.properties.XY.ticks.H.value.fontSize+'px', alignH:'center', alignV:'top' } ); break; case 90: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.H.value.fontName+' '+work.axis.properties.XY.ticks.H.value.fontSize+'px', alignH:'right', alignV:'center' } ); break; default: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.H.value.fontName+' '+work.axis.properties.XY.ticks.H.value.fontSize+'px', alignH:'right', alignV:'top' } ); break; } // draw for(var i=0;i0 && work.axis.properties.XY.ticks.H.visible.big && i%work.axis.properties.XY.ticks.H.frequency.big==0) { canvasObjects.axis.shapeLine(p,0,p,-work.axis.properties.XY.ticks.H.size.big); if(work.axis.properties.XY.ticks.H.value.visible) { canvasObjects.axis.drawingStatePush(); canvasObjects.axis.transformScale({y:-1}); canvasObjects.axis.transformTranslate( { x:p, y:work.axis.properties.XY.ticks.H.size.big+2 } ); canvasObjects.axis.transformRotate({angle:work.axis.properties.XY.ticks.H.value.rotate, mode:'degree'}) canvasObjects.axis.textPrint(work.axis.properties.XY.values.H[i],0,0,'fill'); canvasObjects.axis.drawingStatePop(); } } else if(work.axis.properties.XY.ticks.H.frequency.small>0 && work.axis.properties.XY.ticks.H.visible.small && i%work.axis.properties.XY.ticks.H.frequency.small==0) { canvasObjects.axis.shapeLine(p,0,p,-work.axis.properties.XY.ticks.H.size.small); } } } /* * ------------------------------------------------------------------- * drawing vertical ticks&values * ------------------------------------------------------------------- */ if(work.axis.properties.mode=='XY' && work.axis.properties.display.visible.XY.V) { canvasObjects.axis.shapeLine(0,0,0,work.axis.properties.size.height); // prepare values switch(work.axis.properties.XY.ticks.V.value.rotate) { case 0: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.V.value.fontName+' '+work.axis.properties.XY.ticks.V.value.fontSize+'px', alignH:'right', alignV:'center' } ); break; case 90: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.V.value.fontName+' '+work.axis.properties.XY.ticks.V.value.fontSize+'px', alignH:'center', alignV:'bottom' } ); break; default: canvasObjects.axis.textStyle( { font:work.axis.properties.XY.ticks.V.value.fontName+' '+work.axis.properties.XY.ticks.V.value.fontSize+'px', alignH:'right', alignV:'bottom' } ); break; } //draw small ticks if(work.axis.properties.XY.ticks.V.value.visible && work.axis.properties.XY.ticks.V.frequency.small>0 && work.axis.properties.XY.ticks.V.visible.small) { i=0; while(i<=work.axis.properties.XY.ticks.V.steps) { p=axis.getXYVStepPos(i); canvasObjects.axis.shapeLine(0,p,-work.axis.properties.XY.ticks.V.size.small,p); i+=work.axis.properties.XY.ticks.V.frequency.small; } } //draw big ticks if(work.axis.properties.XY.ticks.V.value.visible && work.axis.properties.XY.ticks.V.frequency.big >0 && work.axis.properties.XY.ticks.V.visible.big) { i=0; while(i<=work.axis.properties.XY.ticks.V.steps) { p=axis.getXYVStepPos(i); canvasObjects.axis.shapeLine(0,p,-work.axis.properties.XY.ticks.V.size.big,p); if(work.axis.properties.XY.ticks.V.value.visible) { canvasObjects.axis.drawingStatePush(); canvasObjects.axis.transformScale({y:-1}); canvasObjects.axis.transformTranslate( { x:-(work.axis.properties.XY.ticks.V.size.big+2), y:-(p+work.axis.properties.XY.ticks.V.value.fontSize/2) } ); canvasObjects.axis.transformRotate({angle:work.axis.properties.XY.ticks.V.value.rotate, mode:'degree'}) canvasObjects.axis.textPrint(i,0,0,'fill'); canvasObjects.axis.drawingStatePop(); } i+=work.axis.properties.XY.ticks.V.frequency.big; } } } /* * ------------------------------------------------------------------- * drawing values for pies * ------------------------------------------------------------------- */ if(work.axis.properties.mode=='pie' && work.axis.properties.display.visible.pie) { var drawSerieValues = function (serie) { var pieWork={ serieProp:serie.get(), tmp:0, angle:0, angle2:0, angCnv:Math.PI/180, pV:0, pH:0, textWidth:0, radiusList:[], distance:0, distance2:0, sumDistance:0, minDistance:10, endRadius:0, startRadius:0, lastZero:0 }; for(var i=0;i=0;i--) { drawSerieValues(work.axis.properties.series[i]); } //restore canvas state canvasObjects.axis.drawingStatePop(); } return(true); }, // drawAxis /** * calculate the legend width, draw the legend */ drawLegend : function (object) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ axis:{ front:(options.axis.front!=null)?options.axis.front.get():null, back:(options.axis.back!=null)?options.axis.back.get():null }, margins:options.margins.get(), legend:options.legend.get(), legendBox:{width:0, height:0, margin:0}, width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight(), tmpTop:0 }, calculateLegendBox = function (axis, canvas, legend, currentHeight, currentWidth) { var returned={width:currentWidth, height:currentHeight, margin:0}, itemHeight=12, tmp=0; if(axis!=null) { if(legend.fontSize>itemHeight) itemHeight=legend.fontSize+4; canvasObjects.axis.textStyle({font:legend.fontSize+'px '+legend.fontName}); for(var i=0; ireturned.width) returned.width=tmp.width; // if serie type is 'pie', use valuesLabels in the legend if(axis.properties.series[i].get().options.get().type=='pie') { for(var j=0;jreturned.width) returned.width=tmp.width; } if(iitemHeight) itemHeight=legend.fontSize+4; for(var i=0; i0)}); tmpTop=drawLegendNames(work.axis.front, canvasObjects.axis, work.legend, 0); tmpTop=drawLegendNames(work.axis.back, canvasObjects.axis, work.legend, tmpTop); // restore canvas state canvasObjects.axis.drawingStatePop(); if(work.legend.position=='left') { canvasObjects.axis.transformTranslate({x:work.legendBox.width+work.legendBox.margin}); canvasObjects.graph.transformTranslate({x:work.legendBox.width+work.legendBox.margin}); //canvasObjects.cursor.transformTranslate({x:work.legendBox.width+work.legendBox.margin}); } setAxisSize(); return(true); }, // drawLegend drawSerieBar : function (object, axis, serie) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ margins:options.margins.get(), axis:axis.get(), width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight(), serieProp:serie.get(), opt:serie.get().options.get() }; // save canvas state canvasObjects.graph.drawingStatePush(); // prepare canvas canvasObjects.graph.styleFillColor(work.opt.backgroundColor); canvasObjects.graph.styleStrokeColor(work.opt.borderColor); canvasObjects.graph.styleStrokeDraw({width:work.opt.borderWidth, cap:'butt', joints:'miter'}); for(var i=0;i0}); } // restore canvas state canvasObjects.graph.drawingStatePop(); }, drawSerieArea : function (object, axis, serie) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ margins:options.margins.get(), axis:axis.get(), width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight(), serieProp:serie.get(), opt:serie.get().options.get(), points:[] }; // save canvas state canvasObjects.graph.drawingStatePush(); // prepare canvas canvasObjects.graph.styleFillColor(work.opt.backgroundColor); canvasObjects.graph.styleStrokeColor(work.opt.borderColor); canvasObjects.graph.styleStrokeDraw({width:work.opt.borderWidth, cap:'butt', joints:'miter'}); //start point work.points=[axis.getXYHPos(0),axis.getXYVStepPos(0)]; for(var i=0;i0) { work.points.splice(0,2); work.points.splice(-1,2); canvasObjects.graph.shapeSimpleShape('open', work.points, {fill:false, stroke:true}); } // restore canvas state canvasObjects.graph.drawingStatePop(); }, drawSerieLine : function (object, axis, serie) { var properties=object.data('properties'), canvasObjects=object.data('canvasObjects'), options=object.data('options'), work={ margins:options.margins.get(), axis:axis.get(), width:canvasObjects.axis.getContextWidth(), height:canvasObjects.axis.getContextHeight(), serieProp:serie.get(), opt:serie.get().options.get(), points:[] }, tmpSize=work.opt.dotSize/2.0; // save canvas state canvasObjects.graph.drawingStatePush(); // prepare canvas canvasObjects.graph.styleFillColor(work.opt.color); canvasObjects.graph.styleStrokeColor(work.opt.color); canvasObjects.graph.styleStrokeDraw({width:work.opt.width, cap:'butt', joints:'miter'}); for(var i=0;i0) { canvasObjects.graph.shapePathArc(0,0,work.opt.innerRadius,work.angle, work.angle2, true,'degree'); canvasObjects.graph.shapePathArc(0,0,work.opt.outerRadius,work.angle2, work.angle, false,'degree'); } else { canvasObjects.graph.shapePathMoveTo(0,0); canvasObjects.graph.shapePathArc(0,0,work.opt.outerRadius,work.angle, work.angle2, true,'degree'); } canvasObjects.graph.shapePathEnd(false, true); work.angle=work.angle2; } if(work.opt.borderWidth>0) { work.angle=0; work.angle2=0; for(var i=0;i0) { canvasObjects.graph.shapePathArc(0,0,work.opt.innerRadius,work.angle, work.angle2, true,'degree'); canvasObjects.graph.shapePathArc(0,0,work.opt.outerRadius,work.angle2, work.angle, false,'degree'); } else { canvasObjects.graph.shapePathMoveTo(0,0); canvasObjects.graph.shapePathArc(0,0,work.opt.outerRadius,work.angle, work.angle2, true,'degree'); } canvasObjects.graph.shapePathEnd(false, false); work.angle=work.angle2; } } // restore canvas state canvasObjects.graph.drawingStatePop(); } }; $.fn.drawingGraph = function(method) { if(publicMethods[method]) { return publicMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if(typeof method === 'object' || ! method) { return publicMethods.init.apply(this, arguments); } else { $.error( 'Method ' + method + ' does not exist on jQuery.drawingGraph' ); } } // $.fn.inputNum } )(jQuery);