CanvasRenderingContext2D.prototype.sector = function (x, y, radius, sDeg, eDeg) { this.save(); this.translate(x, y); this.beginPath(); this.arc(0,0,radius,sDeg, eDeg); this.save(); this.rotate(eDeg); this.moveTo(radius,0); if ((eDeg - sDeg)%(Math.PI*2)!=0) this.lineTo(0,0); //this.lineTo(0,0); this.restore(); this.rotate(sDeg); this.lineTo(radius,0); this.closePath(); this.restore(); return this; } CanvasRenderingContext2D.prototype.clear_canvas = function () { this.clearRect(0,0,10000,10000); return this; } CanvasRenderingContext2D.prototype.clear_arc = function() { this.save(); this.globalCompositeOperation = 'destination-out'; this.fillStyle = 'black'; this.fill(); this.restore(); }; CanvasRenderingContext2D.prototype.clearArc = function(x, y, radius, startAngle, endAngle, anticlockwise) { this.beginPath(); this.arc(x, y, radius, startAngle, endAngle, anticlockwise); this.clear_arc(); }; DVChartList = [DVBarChart,DVPieChart,DVLineChart,DVHistChart,DVRadarChart,DVMulLineChart,DVMulBarChart]; DVCanvasList = []; function DVClone(obj){ if(!obj||"object" != typeof obj){ return null; } var result = (obj instanceof Array)?[]:{}; for(var i in obj){ result[i] = ("object" != typeof obj[i])?obj[i]:DVClone(obj[i]); } return result; } Array.prototype.max = function() { return Math.max.apply({},this) } Array.prototype.min = function() { return Math.min.apply({},this) } /** * The Main Class of DVisual * @constructor * @param {string} canvasName - the canvas's id you want to paint * @example new DVisual(canvas_id); */ function DVisual(canvasName) { reshape_flag = true; for (var i=0;i=0;i--) this.eles[i].draw(this); } /** * A DVisual graph element indicate a dot.(bubble) * @constructor * @example new DVDot({'x':100,'y':100}); * @param {Object[]} args - a array contain arguments below * @param {double} args.x - the x value of the dot * @param {double} args.y - the y value of the dot,0 in default * @param {DVColor=} [args.color = new DVColor()] - the color of the dot,black in default * @param {string=} [args.style ='fill']- the style of this dot,should be one of 'fill','stroke' and 'bubble' * @param {string=} [args.bubbleText ='']- the text show in the bubble * @param {boolean=} [args.shadow ='true'] - whether draw dot's shadow. * @param {double=} [args.radius = '2'] - the radius of this dot(a circle) * @param {double=} [args.lineWidth = '1'] - the lineWidth of this dot(a circle) */ function DVDot(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['x']==null) this.args['x'] = 0; if (args['y']==null) this.args['y'] = 0; if (args['color']==null) this.args['color'] = new DVColor(); if (args['style']==null || (args.style!="fill" && args.style!="stroke" && args.style!="bubble" )) this.args['style'] = "fill"; if (args['bubbleText']==null) this.args['bubbleText'] = ""; if (args['shadow']==null) this.args['shadow'] = true; if (args['radius']==null) this.args['radius'] = 2; if (args['lineWidth']==null) this.args['lineWidth'] = 1; } /** * draw the dot on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw the dot */ DVDot.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); dv.ctx.lineWidth = this.args['lineWidth']; shadow = new DVColor(100,100,100,0.3); if (this.args['shadow']) { if (this.shadowDot == null) { shadowArgs = DVClone(this.args); shadowArgs['color'] = new DVColor(100,100,100,0.3); shadowArgs['shadow'] = false; shadowArgs['x']+=1; shadowArgs['y']+=1; shadowArgs['description'] = ""; this.shadowDot = new DVDot(shadowArgs); } this.shadowDot.draw(dv); } if (this.args['style']=='stroke') { dv.ctx.sector(this.args.x,this.args.y,this.args.radius,0,2*Math.PI); dv.ctx.stroke(); } if (this.args['style']=='fill') { dv.ctx.sector(this.args.x,this.args.y,this.args.radius,0,2*Math.PI); dv.ctx.fill(); } if (this.args['style']=='bubble') { dv.ctx.sector(this.args.x,this.args.y,this.args.radius,0,2*Math.PI); dv.ctx.stroke(); a = this.args.color.a; if (this.args.color.a>0.7) a = 0.4; dv.ctx.fillStyle = (new DVColor(this.args.color.r,this.args.color.g,this.args.color.b,a)).tostring(); dv.ctx.sector(this.args.x,this.args.y,this.args.radius,0,2*Math.PI); dv.ctx.fill(); if (this.args.bubbleText.length>0) { testStr = this.args.bubbleText; if (dv.ctx.measureText("D").width>dv.ctx.measureText("testStr").width) teststr = 'D'; rightfont = DVgetRightTextStyleByStrLenght(dv,teststr,this.args.radius*1.5); dv.ctx.font = rightfont; dv.ctx.textAlign = 'center'; dv.ctx.fillStyle = '#FFF'; dv.ctx.fillText(this.args.bubbleText,this.args.x,this.args.y+dv.ctx.measureText("D").width*1.0/2); dv.ctx.closePath(); } } dv.ctx.restore(); } /** * A DVisual graph element indicate a text * @constructor * @example new DVDot({'x':100,'y':100,'font'="13px Arial"}); * @param {Object[]} args - a array contain arguments below * @param {double} args.x - the x value of the dot * @param {double} args.y - the y value of the dot,0 in default * @param {string} args.text - the text content you want to draw * @param {string=} [args.font="8px Arial"] - the text's font * @param {DVColor=} [args.color = new DVColor()] - the color of the dot,black in default * @param {string=} [args.style ='fill']- the style of this dot,should be one of 'fill','stroke' * @param {boolean=} [args.shadow =true] - whether draw text's shadow. * @param {double=} [args.maxwidth =-1] - the limited width of printed text,-1 means no limit * @param {string=} [args.textAlign = 'left'] - the text align of printed text position * @param {string=} [args.direction = 'horizontal'] - the direction of text:horizontal or vertical * @param {double=} [args.lineWidth = '1'] - the lineWidth of text * @param {double=} [args.rotate = 0] - the lineWidth of text */ function DVText(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['x']==null) this.args['x'] = 0; if (args['y']==null) this.args['y'] = 0; if (args['text']==null) this.args['text'] = ""; if (args['font']==null) this.args['font'] = "8px Arial"; if (args['color']==null) this.args['color'] = new DVColor(); if (args['style']==null || (args.style!="stroke" && args.style!="fill")) this.args['style'] = "fill"; if (args['shadow']==null) this.args['shadow'] = true; if (args['maxwidth']==null) this.args['maxwidth'] = -1; if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['rotate']==null) this.args['rotate'] = 0; if (args['textAlign']==null) this.args['textAlign'] = 'left'; if (args['direction']==null || (args['direction']!='vertical' && args['direction']!='horizontal')) this.args['direction'] = 'horizontal'; } /** * draw the text on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVText.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); dv.ctx.font = this.args['font']; dv.ctx.lineWidth = this.args['lineWidth']; dv.ctx.textAlign = this.args['textAlign']; dv.ctx.beginPath(); shadow = new DVColor(100,100,100,0.3); if (this.args['shadow']) { if (this.shadowText == null) { shadowArgs = DVClone(this.args); shadowArgs['color'] = new DVColor(100,100,100,0.3); shadowArgs['shadow'] = false; shadowArgs['x']+=1; shadowArgs['y']+=1; this.shadowText = new DVText(shadowArgs); } this.shadowText.draw(dv); } x = this.args.x; y = this.args.y; if (this.args.direction=='vertical') { dv.ctx.rotate(-Math.PI/2) tmp = x; x = -y; y = tmp; } if (this.args.rotate!=0) { dv.ctx.translate(x,y); x = 0; y = 0; dv.ctx.rotate(this.args.rotate); } if (this.args['style']=='stroke') { if (this.args['maxwidth']==-1) dv.ctx.strokeText(this.args.text,x,y); else dv.ctx.strokeText(this.args.text,x,y,this.args['maxwidth']); } if (this.args['style']=='fill') { if (this.args['maxwidth']==-1) dv.ctx.fillText(this.args.text,x,y); else dv.ctx.fillText(this.args.text,x,y,this.args['maxwidth']); } if (this.args.direction=='vertical') { dv.ctx.rotate(Math.PI/2); } if (this.args.rotate!=0) { dv.ctx.rotate(-this.args.rotate); dv.ctx.translate(-this.args.x,-this.args.y); } dv.ctx.fill(); dv.ctx.closePath(); dv.ctx.restore(); } /** * A DVisual graph element indicate a line * @constructor * @example new DVLine({'beginX':100,'beginY':100,'endX':20,'endY':20,'style':'dash'}); * @param {Object[]} args - a array contain arguments below * @param {double} args.beginX - the x value of the start node * @param {double} args.beginY - the y value of the start node * @param {double} args.endX - the x value of the stop node * @param {double} args.endY - the y value of the stop node * @param {DVColor=} [args.color = new DVColor()] - the color of the dot,black in default * @param {string=} [args.style ='real']- the style of this dot,should be one of 'real','dash' * @param {boolean=} [args.shadow =true] - whether draw the line's shadow. * @param {double=} [args.lineWidth = '1'] - the lineWidth of line */ function DVLine(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['beginX']==null) this.args['beginX'] = 0; if (args['beginY']==null) this.args['beginY'] = 0; if (args['endX']==null) this.args['endX'] = 0; if (args['endY']==null) this.args['endY'] = 0; if (args['color']==null) this.args['color'] = new DVColor(); if (args['style']==null || (args.style!="real" && args.style!="dash")) this.args['style'] = "real"; if (args['shadow']==null) this.args['shadow'] = true; if (args['lineWidth']==null) this.args['lineWidth'] = 1; } /** * get the shadow according to the line's direction * @function * @return [0,1] */ DVLine.prototype.getShadow = function() { // if ((this.args.beginXthis.args.endX && this.args.beginY>this.args.endY)) // return [0,-1] return [0,1] } /** * whether the node in the lines's region * @function * @param {double} x -the x value of test node * @param {double} y -the y value of test node * @return {boolean} result -whether (x,y) is in the line's region */ DVLine.prototype.between =function(x,y) { if (x>=Math.min(this.args['beginX'],this.args['endX']) && x<=Math.max(this.args['beginX'],this.args['endX']) && y>=Math.min(this.args['beginY'],this.args['endY']) && y<=Math.max(this.args['beginY'],this.args['endY'])) return true; return false; } /** * draw the line on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVLine.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); dv.ctx.lineWidth = this.args['lineWidth']; if (this.args['shadow']) { if (this.shadowLine==null) { shadowArgs = DVClone(this.args); shadowArgs['color'] = new DVColor(100,100,100,0.3); shadowArgs['shadow'] = false; shadow = this.getShadow(); shadowArgs['beginX']+=shadow[0]; shadowArgs['beginY']+=shadow[1]; shadowArgs['endX']+=shadow[0]; shadowArgs['endY']+=shadow[1]; this.shadowLine = new DVLine(shadowArgs); } this.shadowLine.draw(dv); } if (this.args['style']=='real') { dv.ctx.beginPath(); dv.ctx.moveTo(this.args.beginX,this.args.beginY); dv.ctx.lineTo(this.args.endX,this.args.endY); dv.ctx.closePath(); dv.ctx.fill(); dv.ctx.stroke(); } if (this.args['style']=='dash') { dv.ctx.beginPath(); xinc = this.args['endX'] - this.args['beginX']; yinc = this.args['endY'] - this.args['beginY']; length = Math.sqrt(xinc*xinc+yinc*yinc); doted = Math.max(length*1.0/50,5); xinc*=doted/length; yinc*=doted/length; x = this.args['beginX']; y = this.args['beginY']; while (this.between(x+xinc,y+yinc)) { dv.ctx.moveTo(x,y) dv.ctx.lineTo(x+xinc,y+yinc) x+=2*xinc; y+=2*yinc; } dv.ctx.moveTo(x,y) dv.ctx.lineTo(this.args['endX'],this.args['endY']) dv.ctx.closePath(); dv.ctx.stroke(); } dv.ctx.restore(); } /** * A DVisual graph element indicate a quadratic Curve * @constructor * @example new DVLine({'beginX':100,'beginY':100,'endX':20,'endY':20,'style':'dash'}); * @param {Object[]} args - a array contain arguments below * @param {double} args.beginX - the x value of the start node * @param {double} args.beginY - the y value of the start node * @param {double} args.endX - the x value of the stop node * @param {double} args.endY - the y value of the stop node * @param {double} args.cpx - the x value of the control node * @param {double} args.cpy - the y value of the control node * @param {DVColor=} [args.color = new DVColor()] - the color of the dot,black in default * @param {double=} [args.lineWidth = '1'] - the lineWidth of line */ function DVCurve(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['beginX']==null) this.args['beginX'] = 0; if (args['beginY']==null) this.args['beginY'] = 0; if (args['endX']==null) this.args['endX'] = 0; if (args['endY']==null) this.args['endY'] = 0; if (args['color']==null) this.args['color'] = new DVColor(); if (args['lineWidth']==null) this.args['lineWidth'] = 1; } /** * draw the curve on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVCurve.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); dv.ctx.lineWidth = this.args['lineWidth']; dv.ctx.beginPath(); dv.ctx.moveTo(this.args.beginX,this.args.beginY); dv.ctx.quadraticCurveTo(this.args.cpx,this.args.cpy,this.args.endX,this.args.endY); dv.ctx.stroke(); dv.ctx.restore(); } /** * A DVisual graph element indicate a polygon * @constructor * @example new DVPolygon({'X':[10,10,20,20],'Y':[10,20,20,10],'style':'stroke'}); * @param {Object[]} args - a array contain arguments below * @param {Array(double)} args.X - the set of a series nodes' x value * @param {Array(double)} args.Y - the set of a series nodes' y value * @param {DVColor=} [args.color = new DVColor()] - the color of the dot,black in default * @param {string=} [args.style ='fill']- the style of this dot,should be one of 'fill','stroke' * @param {boolean=} [args.shadow =true] - whether draw text's shadow. * @param {double=} [args.lineWidth = '1'] - the lineWidth of text */ function DVPolygon(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (this.args.X.length!=this.args.Y.length) return null; if (args['color']==null) this.args['color'] = new DVColor(); if (args['style']==null || (args.style!="fill" && args.style!="stroke" && args.style!="transFill")) this.args['style'] = "transFill"; if (args['shadow']==null) this.args['shadow'] = true; if (args['lineWidth']==null) this.args['lineWidth'] = 1; } /** * draw the polygon on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVPolygon.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); dv.ctx.lineWidth = this.args['lineWidth']; if (this.args['shadow']) { if (this.shadowPoly==null) { shadowArgs = DVClone(this.args); shadowArgs['color'] = new DVColor(200,200,200,0.3); shadowArgs['shadow'] = false; for (var i=0;i=this.args.classes.length) break; result = dv.xyTrans(x,y); str = x + ""; if (this.args['xStyle']=='class') str = this.args.classes[x-0.5]; metrics = dv.ctx.measureText(str); x_kedu_arg = {'x':result[0]-metrics.width/2,'y':result[1]+ dv.ctx.measureText("D").width+8,'text':str,'lineWidth':this.args['lineWidth']}; x_kedu_line_arg = {'beginX':result[0],'beginY':result[1],'endX':result[0],'endY':result[1]-5}; if (this.args.xGrid) { color = new DVColor(100,100,100,0.1); if (dv.Xinc<0 && x==0) color = new DVColor(256,0,0,0.3); xgrid_line = {'beginX':result[0],'beginY':result[1],'endX':result[0],'endY':0,'color':color,'shadow':false}; this.eles.push(new DVLine(xgrid_line)); } this.eles.push(new DVText(x_kedu_arg)); this.eles.push(new DVLine(x_kedu_line_arg)); x += this.args.xSpan; if (this.args['xStyle']=='class' && x>=this.args.classes.length) break; } if (this.args['yDescript']!="") { x_des_arg = {'x':21,'y':40-2,'text':this.args['yDescript'],'textAlign':'center','maxwidth':40,'direction':'vertical'} x_des_poly_arg = {'X':[dv.originX,dv.originX-15,dv.originX-15,dv.originX-7.5,dv.originX], 'Y':[20+40,20+40,20,10,20],'style':'stroke'} this.eles.push(new DVPolygon(x_des_poly_arg)); this.eles.push(new DVText(x_des_arg)); } x = dv.Xinc; y = dv.Yinc; count = 0; while (dv.xyTrans(x,y)[1]>70) { result = dv.xyTrans(x,y); if (this.args.yStyle=='value') str = y+""; else if (this.args.yStyle=='percentage') str = y.toFixed(2)*100+"%"; else if (this.args.yStyle=='class' && count=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Legend,an important structure of most chart * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.classes - the classes's texts for the legend * @param {Array(DVColor)=} [args.colors=DVgetRandomColor(this.args.classes.length,0.7);] - the classes's colors for the legend * @param {double} args.x - the x value of the Legend's start node(left bottom node) * @param {double} args.y - the y value of the Legend's start node(left bottom node) * @param {string=} [args.style='rect'] - the legend's note shape for each class,'rect','line' or 'bubble' * @param {boolean=} [args.outerbox='true'] - whether draw the outerbox of legend * @param {string=} [args.direction='vertical'] - the direction of legend,'vertical' means put all data in a column.'horizontal' means in a row * @param {double=} [args.height=!!according to the canvas!!] - the height limit of Legend * @param {double=} [args.width=!!according to the canvas!!] - the width limit of Legend */ function DVLegend(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['classes']==null) this.args['classes'] = ["A",'B','C']; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args.classes.length,0.7); if (args['x']==null) this.args['x'] = 100; if (args['y']==null) this.args['y'] = 100; if (args['style']==null || (args['style']!='rect' && args['style']!='line' && args['style']!='bubble')) this.args['style'] = 'rect'; if (args['outerbox']==null) this.args['outerbox'] = true; if (args['direction']==null || (args['direction']!='vertical' && args['direction']!='horizontal') ) this.args['direction'] = 'vertical'; if (args['height']==null) this.args['height'] = 0; if (args['width']==null) this.args['width'] = 0; this.eles = new Array(); } /** * get the legend's height and width according to the dvisual instance * @function * @param {DVisual} dv - the Dvisual instance you want to draw * @return {Array} result - [height,width] */ DVLegend.prototype.getHeightWidth =function(dv) { if (this.args['direction']=='vertical') return [dv.yLenTrans((dv.Ymargin*1.0/6)),dv.xLenTrans((dv.Xmargin*1.0/5))] return [20,dv.xLenTrans((dv.Xmargin*1.0*2/3))] } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVLegend.prototype.prepare = function(dv) { if (this.args['width']==0 && this.args['height']==0) { this.args['height'] = this.getHeightWidth(dv)[0]; this.args['width'] = this.getHeightWidth(dv)[1]; } if (this.args.direction=='vertical') TextHeight = this.args['height']/(this.args.classes.length*4.0/3); else TextHeight = 20.0/4*3; drawXinc = 0.0; drawYinc = 0.0; drawLength = this.args['width']/(6.0/5); if (this.args.direction=='vertical') drawYinc = TextHeight*4.0/3; else { drawXinc = this.args['width']/(6.0/5*this.args.classes.length)*6/5; drawLength = this.args['width']/(6.0/5*this.args.classes.length); } font = DVgetRightTextStyle(dv,TextHeight*0.5); boxtopy = this.args.y-this.args.height; dv.ctx.save(); dv.ctx.font = font; maxlength = 0; for (var i=0;idrawLength*(1-ratio)*1.0) { ratio = (1 - maxlength*1.0/drawLength)*0.6+ratio*0.4; } if (this.args.style=='rect') this.eles.push(new DVRect({'x':paintX,'y':paintY,'width':drawLength*ratio,'height':TextHeight,'style':'fill', 'color':this.args.colors[i]})); else if (this.args.style=='line') this.eles.push(new DVLine({'beginX':paintX,'beginY':paintY+TextHeight*1.0/2, 'endX':paintX + drawLength*ratio,"endY":paintY+TextHeight*1.0/2, 'color':this.args.colors[i],'lineWidth':3})); else if (this.args.style=='bubble') { this.eles.push(new DVDot({'x':paintX+drawLength*ratio/3,'y':paintY+TextHeight*1.0/2,'radius':TextHeight*1.0/2,'style':'bubble','color':this.args.colors[i]})); //ratio*=3.0/4; } this.eles.push(new DVText({'text':this.args.classes[i],'x':paintX + drawLength*ratio+drawLength*(1-ratio)*1.0*0+2,'y':paintY+TextHeight*1.0/1.3,'textAlign':'left', 'maxwidth':drawLength*(1-ratio)*1.0,'font':font})) } dv.ctx.restore(); if (this.args.outerbox) { if (ratio==0.5 && this.args.direction=='vertical') width = this.args.width*ratio+maxlength+8 else width = this.args.width; this.eles.push(new DVRect({'x':this.args.x,'y':boxtopy,'width':width,'height':this.args.height,'style':'fill', 'color':new DVColor(30,144,255,0.3)})) } } /** * draw the Coordinate on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVLegend.prototype.draw = function(dv) { if (this.eles.length==0) { this.prepare(dv); } for (var i=this.eles.length-1;i>-1;i--) this.eles[i].draw(dv); } /** * get the fitted font style according to the height of text * @function * @param {DVisual} dv - the Dvisual instance you want to draw * @param {double} length - the height limit of text * @return {string} font - the fitted font string. */ DVgetRightTextStyle = function(dv,length) { dv.ctx.save(); i = 0; for (i=1;i<100;i++) { dv.ctx.font = i+"px Arial"; if (dv.ctx.measureText("D").width>length) { i = i - 1; dv.ctx.restore(); return i+"px Arial"; } } dv.ctx.restore(); return i + "px Arial"; } /** * get the fitted font style according to text and the length limit of text * @function * @param {DVisual} dv - the Dvisual instance you want to draw * @param {string} str - the text you want to draw * @param {double} length - the height limit of text * @return {string} font - the fitted font string. */ DVgetRightTextStyleByStrLenght = function(dv,str,length) { dv.ctx.save(); i = 0; for (i=7;i<100;i++) { dv.ctx.font = i+"px Arial"; if (dv.ctx.measureText(str).width>length) { i = i - 1; dv.ctx.restore(); return i+"px Arial"; } } dv.ctx.restore(); return i + "px Arial"; } /** * A DVisual graph element indicate a LineChart,integrate the dot,line,area or bubble chart for a single path * @constructor * @example new DVLineChart({'X':[1,2,3,4,5],'Y':[1,2,3,4,5],'style':'area|dot'}); * @param {Object[]} args - a array contain arguments below * @param {Array(double)} args.X - the set of a series nodes' x value * @param {Array(double)} args.Y - the set of a series nodes' y value * @param {string=} [args.style='dot|line'] - the legend's note shape for each class,'dot','line','area' can be used simultaneously,'bubble' style is unique * @param {DVColor=} [args.color = new DVColor(256,0,0,0.8)] - the color of the line/dot/area/bubble * @param {double=} [args.lineWidth = '1'] - the lineWidth of graph * @param {string=} [args.xDescript='x'] - the X axes's description * @param {string=} [args.yDescript='y'] - the Y axes's description * @param {boolean=} [args.xGrid=true] - whether draw the grid line started from X axes * @param {boolean=} [args.yGrid=true] - whether draw the grid line started from Y axes * @param {Array(double)} args.bubbleRadius - when the style is bubble,you should indicate the radius for each bubble */ function DVLineChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (args['style']==null) this.args['style'] = 'dot|line'; if (args['color']==null) this.args['color'] = new DVColor(256,0,0,0.8); if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['xDescript']==null) this.args['xDescript'] = "x"; if (args['yDescript']==null) this.args['yDescript'] = "y"; if (args['xGrid']==null) this.args['xGrid'] = true; if (args['yGrid']==null) this.args['yGrid'] = true; if (args['bubbleRadius']==null) this.args['bubbleRadius'] = []; this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVLineChart.prototype.prepare = function(dv) { if (!dv.drawed) { dv.initial(this.args.X,this.args.Y); ySpan = DVGetSpan(dv.Ymargin) xSpan = DVGetSpan(dv.Xmargin) cord_arg = {'xGrid':this.args.xGrid,'yGrid':this.args.yGrid,'xDescript':this.args.xDescript,'yDescript':this.args.yDescript, 'xSpan':xSpan,'ySpan':ySpan} this.eles.push(new DVCoordinate(cord_arg)); dv.initialZ(this.args.bubbleRadius); } Xs = new Array(); Ys = new Array(); for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * get a random number in certain margin * @function * @param {double} N - the margin of random number you want * @return {double} randomN - the random number */ function getrandom(N) { return Math.floor(Math.random() * ( N + 1)); } /** * get a series of DVColor * @function * @param {int} lens - how many colors you want. * @param {double=} [alpha=0.7] - the alpha component * @return {Array()} randomN - the random color set */ function DVgetRandomColor(lens,alpha) { result = new Array(); if (arguments.length==1) alpha = 0.7; for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Bar Chart,integrate the normal,stacked bar chart. * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.X - a list of string for each x-label * @param {Array(double)} args.Y - the set of a series value * @param {string=} [args.style='bar'] - the style of bar chart,'stacked' or 'bar' * @param {Array(Array(double))} args.stackedY - use for stacked bar chart,for each element in this array have #stacked_component numbers. * @param {Array(string)} args.stackedClass - a series of string indicate each stacked_component class. * @param {Array(DVColor)} args.stackedColors - a series of DVColor indicate each stacked_component class. * @param {int} args.all - how many bar you want for each X-label * @param {int} args.index - current data is the i-th bar for the each X-label * @param {DVColor=} [args.color = new DVColor(256,0,0,0.8)] - the color of the bar(normal bar) * @param {boolean=} [args.xGrid=false] - whether draw the grid line started from X axes * @param {boolean=} [args.yGrid=true] - whether draw the grid line started from Y axes * @param {string=} [args.xDescript='x'] - the X axes's description * @param {string=} [args.yDescript='y'] - the Y axes's description * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend */ function DVBarChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (args['style']==null || (args['style']!='bar' && args['style']!='stacked')) this.args['style'] = 'bar'; if (args['stackedY']==null) this.args['stackedY'] = [[]]; if (args['stackedClass']==null) this.args['stackedClass'] = []; if (args['stackedColor']==null) this.args['stackedColor'] = DVgetRandomColor(this.args['stackedClass'].length); if (args['all']==null) this.args['all'] = 1; if (args['index']==null) this.args['index'] = 1; if (args['color']==null) this.args['color'] = new DVColor(256,0,0,0.8); if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['xDescript']==null) this.args['xDescript'] = "x"; if (args['yDescript']==null) this.args['yDescript'] = "y"; if (args['xGrid']==null) this.args['xGrid'] = false; if (args['yGrid']==null) this.args['yGrid'] = true; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = false; this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVBarChart.prototype.prepare = function(dv) { if (!dv.drawed) { if (this.args.style=='bar') dv.initial([0,this.args.X.length],this.args.Y); else { max_sum = 0; for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Muliple Bar Chart * @constructor * @param {Object} args - a array contain arguments below * @param {Array(string)} args.X - a list of string for each x-label * @param {Array(Array(double))} args.Ys - 2d Array,indicate a series bar value for each x-label. * @param {Array(string)} args.Z - a list of string indicate each kind of bar * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend * @param {Array(DVColor)=} [args.colors=DVgetRandomColor(this.args['Z'].length)] - a series of DVColor indicate each kind of bar. * @param {boolean=} [args.xGrid=false] - whether draw the grid line started from X axes * @param {boolean=} [args.yGrid=true] - whether draw the grid line started from Y axes * @param {string=} [args.xDescript='x'] - the X axes's description * @param {string=} [args.yDescript='y'] - the Y axes's description */ function DVMulBarChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Ys']==null) this.args['Ys'] = [[]]; if (args['Z']==null) this.args['Z'] = []; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = false; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args['Z'].length); if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['xDescript']==null) this.args['xDescript'] = "x"; if (args['yDescript']==null) this.args['yDescript'] = "y"; if (args['xGrid']==null) this.args['xGrid'] = false; if (args['yGrid']==null) this.args['yGrid'] = true; this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVMulBarChart.prototype.prepare = function(dv) { dv.drawed = true; ymm = DV2dArrMinMax(this.args.Ys); dv.initial([0,this.args.X.length],ymm); ySpan = DVGetSpan(dv.Ymargin) xSpan = 1; cord_arg = {'xGrid':this.args.xGrid,'yGrid':this.args.yGrid,'xDescript':this.args.xDescript,'yDescript':this.args.yDescript, 'xSpan':xSpan,'ySpan':ySpan,'xStyle':'class','classes':this.args.X} this.eles.push(new DVCoordinate(cord_arg)); for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Histgram Chart * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(double)} args.X - a series of value,the hist chart will be created by this data * @param {DVColor=} [args.color = new DVColor(256,0,0,0.8)] - the color of the bar(normal bar) * @param {sec=} [args.sec = this.getsec(this.args.X)] - the segment for the input data for each hist,will be calculate in default. * @param {string=} [args.yStyle='value'] - show the value of each bar or the percentage,'value' or 'percentage' * @param {double=} [args.lineWidth = '1'] - the lineWidth of graph * @param {string=} [args.xDescript='x'] - the X axes's description * @param {string=} [args.yDescript='y'] - the Y axes's description * @param {boolean=} [args.xGrid=false] - whether draw the grid line started from X axes * @param {boolean=} [args.yGrid=true] - whether draw the grid line started from Y axes */ function DVHistChart(args) { if (arguments.length==0) args = {}; this.incX = 0.0; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['color']==null) this.args['color'] = new DVColor(142,214,249,1); if (args['sec']==null) this.args['sec'] = this.getsec(this.args.X); if (args['yStyle']==null || (this.args['yStyle']!='value' && this.args['yStyle']!='percentage')) this.args['yStyle'] = "value"; if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['xDescript']==null) this.args['xDescript'] = "x"; if (args['yDescript']==null) this.args['yDescript'] = "y"; if (args['xGrid']==null) this.args['xGrid'] = false; if (args['yGrid']==null) this.args['yGrid'] = true; this.eles = new Array(); } /** * calculate the segment if the user haven't set. * @function * @param {Array(double)} X - the set of input data * @return {double} sec - the segment ofr the hist chart */ DVHistChart.prototype.getsec = function(X) { this.incX = 0.0; xmargin = this.oldWidth; if (X.length!=0) { xm = (X.max()-X.min())*1.0; if ((xm/X.max())<0.3) this.incX = Math.floor(X.min())-1; xmargin = X.max()-incX; if (xmargin<=5) return 0.5; if (xmargin<=10) return 1; if (xmargin<=50); return 5; if (xmargin<=100); return 10; if (xmargin<=500); return 50; } return 1; } /** * get the span for a settled margin * @function * @param {double} margin - the margin * @return {double} Span - the span for the input margin */ function DVGetSpan(margin) { Span = 1; if (margin<0.5) Span = 0.05; else if (margin<1) Span = 0.1; else if (margin<5) Span = 0.5; else if (margin<15) Span = 1; else if (margin<50) Span = 5; else if (margin<100) Span = 10; else if (margin<500) Span = 50; else if (margin<1000) Span = 100; return Span; } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVHistChart.prototype.prepare = function(dv) { xSpan = this.args.sec; this.Ysum = new Array(); //alert((this.args.X.max()-this.incX)/xSpan+1) for (var i=0;i<(this.args.X.max()-this.incX)/xSpan+1;i++) this.Ysum.push(0) for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a sector * @constructor * @param {Object[]} args - a array contain arguments below * @param {double} args.x - the center's x value * @param {double} args.y - the center's y value * @param {double} args.radius - the radius of sector * @param {double} args.sDeg - the stared angle Degree * @param {double} args.eDeg - the end angle Degree * @param {DVColor=} [args.color = DVgetRandomColor(1,0.6)[0]] - the color of the dot,random in default * @param {boolean=} [args.pop =false] - whether poo out this sector * @param {boolean=} [args.shadow =true] - whether draw text's shadow. * @param {string=} [args.style ='fill']- the style of this sector,should be one of 'fill','stroke','transFill' means translucent fill. * @param {string=} [args.innerText ='']- the text you want to shao in the center of sector * @param {double=} [args.ring_ratio = 0] - the ring ratio,to calculate the text location */ function DVSector(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['x']==null) this.args['x'] = 100; if (args['y']==null) this.args['y'] = 100; if (args['radius']==null) this.args['radius'] = 50; if (args['sDeg']==null) this.args['sDeg'] = 0; if (args['eDeg']==null) this.args['eDeg'] = 0; if (args['color']==null) this.args['color'] = DVgetRandomColor(1,0.6)[0]; if (args['shadow']==null) this.args['shadow'] = true; if (args['ring_ratio']==null) this.args['ring_ratio'] = 0; if (args['pop']==null) this.args['pop'] = false; if (args['style']==null || (args.style!="fill" && args.style!="stroke" && args.style!="transFill")) this.args['style'] = "fill"; if (args['innerText']==null) this.args['innerText'] = ""; if (args['outerText']==null) this.args['outerText'] = ""; if (this.args['pop']) { this.args['x']+=this.args.radius/20*Math.cos((this.args.sDeg + this.args.eDeg)*1.0/2); this.args['y']+=this.args.radius/20*Math.sin((this.args.sDeg + this.args.eDeg)*1.0/2); } } /** * draw the sector on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVSector.prototype.draw = function(dv) { dv.ctx.save(); dv.ctx.fillStyle = this.args.color.tostring(); dv.ctx.strokeStyle = this.args.color.tostring(); if (this.args['shadow']) { if (this.shadowSector == null) { shadowArgs = DVClone(this.args); shadowArgs['color'] = new DVColor(100,100,100,0.3); shadowArgs['shadow'] = false; shadowArgs['pop'] = false; shadowArgs['radius']*=1.01; shadowArgs['x']+=shadowArgs.radius/50*Math.cos((shadowArgs.sDeg + shadowArgs.eDeg)*1.0/2); shadowArgs['y']+=shadowArgs.radius/50*Math.sin((shadowArgs.sDeg + shadowArgs.eDeg)*1.0/2); shadowArgs['innerText'] = ""; shadowArgs['outerText'] = ""; this.shadowSector = new DVSector(shadowArgs); } this.shadowSector.draw(dv); } if (this.args.style=='stroke' || this.args.style=='fill') { dv.ctx.sector(this.args.x,this.args.y,this.args.radius,this.args.sDeg,this.args.eDeg); if (this.args.style=='fill') dv.ctx.fill(); else dv.ctx.stroke(); } else { dv.ctx.sector(this.args.x,this.args.y,this.args.radius,this.args.sDeg,this.args.eDeg); dv.ctx.stroke(); dv.ctx.fillStyle = (new DVColor(this.args.color.r,this.args.color.g,this.args.color.b,0.5)).tostring(); dv.ctx.sector(this.args.x,this.args.y,this.args.radius,this.args.sDeg,this.args.eDeg); dv.ctx.fill(); } if (this.args.innerText!="") { if (this.innerDV==null) { r = this.args.radius/(1/Math.sin((this.args.eDeg - this.args.sDeg)/2)+1) //扇形内最大圆半径 if (r>this.args.radius*(1-this.args.ring_ratio)*1.0/2.2) { r = this.args.radius*(1-this.args.ring_ratio)*1.0/2.2; } teststr = this.args.innerText; //alert(teststr.length) if (teststr[teststr.length-1]=="%" && teststr.length<3) teststr = "12%"; font = DVgetRightTextStyleByStrLenght(dv,teststr,Math.min(1.7*r,Math.min(dv.oldWidth,dv.oldHeight)*1.0/10)); dv.ctx.font = font; yinc = dv.ctx.measureText('D').width/2; textX = this.args.x + (this.args.radius-r)*Math.cos((this.args.sDeg + this.args.eDeg)*1.0/2); textY = this.args.y + (this.args.radius-r)*Math.sin((this.args.sDeg + this.args.eDeg)*1.0/2)+yinc; if (this.args.ring>0) { textX = this.args.x + (this.args.radius-r)*Math.cos((this.args.sDeg + this.args.eDeg)*1.0/2); textY = this.args.y + (this.args.radius-r)*Math.sin((this.args.sDeg + this.args.eDeg)*1.0/2)+yinc; } this.innerDV = new DVText({'maxwidth':1.7*r,'text':this.args.innerText,'x':textX,'y':textY,'textAlign':'center','color':new DVColor(256,256,256,1),'font':font}) } this.innerDV.draw(dv); } dv.ctx.restore(); } /** * A DVisual graph element indicate a Pie Chart * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.X - a series of string,indicate for each component on the pie * @param {Array(double)} args.Y - a series of value,the hist chart will be created by this data * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend * @param {Array(DVColor)=} [args.colors = DVgetRandomColor(this.args.X.length)] - the colors for each component * @param {douboe=} [args.ring_ratio = 0] - the ring ratio of the pie,0 in default,means no ring * @param {Array(string)=} [args.text=!!label+':'+value!!] - a series of string you want to show on each sector on the pie. * @param {string=} [args.style='showPercentage'] - show the value of each bar or the percentage,'empty' or 'showtext' or 'showPercentage',or 'ring' to show a ring chart */ function DVPieChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = false; if (args['ring_ratio']==null || args['ring_ratio']>1 || args['ring_ratio']<0) this.args['ring_ratio'] = 0; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args.X.length); if (args['text']==null) { this.args['text'] = new Array(); for (var i=0;i=0;i--) this.eles[i].draw(dv); D = Math.min(dv.oldWidth,dv.oldHeight); dv.ctx.clearArc(D/2-D/15,D/2-D/15,D*1.0/6*3*this.args.ring_ratio,0,Math.PI*2); } /** * A DVisual graph element indicate a Radar Chart * @constructor * @example new DVRadarChart({'X':["型号1","型号2"],'Y':[[6,7,3,5,6,9],[8,6,7,2,8,6]],'arguments':["速度","能力","强度","战斗力","成本","价格"]}) * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.X - a series of string,indicate for each player you want to draw,() * @param {Array(Array(double))} args.Y - a series of value,it's length should be player's number,each element of this should be an array for arguments' number * @param {Array(string)} args.arguments - a series of string,indicate each arguments. * @param {double=} [args.argumax=10] - the maxium value for argument.(unified for all argument) * @param {double=} [args.argumin=0] - the minium value for argument.(unified for all argument) * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend * @param {Array(DVColor)=} [args.colors = !!randomColor!!] - the colors for each player */ function DVRadarChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (args['arguments']==null) this.args['arguments'] = []; if (args['argumax']==null) this.args['argumax'] = 10; if (args['argumin']==null) this.args['argumin'] = 0; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = false; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args.X.length,0.4); this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVRadarChart.prototype.prepare = function(dv) { Deg = (Math.PI*2)/this.args.arguments.length; D = Math.min(dv.oldWidth,dv.oldHeight); oX = D/2; oY = D/2; r = D*1.0/2/6*5; for (var step=0;step<=5;step++) { tmpX =[] tmpY =[] if (step==5) color = new DVColor(); else color = new DVColor(100,100,100,0.2); for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Area Pie Chart,all arguments are same with Pie Chart,bu different style of image * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.X - a series of string,indicate for each component on the pie * @param {Array(double)} args.Y - a series of value,the hist chart will be created by this data * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend * @param {Array(DVColor)=} [args.colors = DVgetRandomColor(this.args.X.length)] - the colors for each component * @param {Array(string)=} [args.text=!!label+':'+value!!] - a series of string you want to show on each sector on the pie. * @param {string=} [args.style='showPercentage'] - show the value of each bar or the percentage,'empty' or 'showtext' or 'showPercentage' */ function DVAreaPieChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Y']==null) this.args['Y'] = []; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = false; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args.X.length); if (args['text']==null) { this.args['text'] = new Array(); for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Box Chart,integrate the normal,stacked bar chart. * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.X - a list of string for each x-label * @param {Array(Array(double))} args.Ys - the value set of each x. * @param {Array(DVColor)} args.colors - a series of DVColor indicate each x. * @param {boolean=} [args.xGrid=false] - whether draw the grid line started from X axes * @param {boolean=} [args.yGrid=false] - whether draw the grid line started from Y axes * @param {string=} [args.xDescript='x'] - the X axes's description * @param {string=} [args.yDescript='y'] - the Y axes's description * @param {boolean=} [args.legendOuterBox=true] - whether draw the outer box of legend */ function DVBoxChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['X']==null) this.args['X'] = []; if (args['Ys']==null) this.args['Y'] = []; if (args['style']==null || (args['style']!='bar' && args['style']!='stacked')) this.args['style'] = 'bar'; if (args['colors']==null) this.args['colors'] = DVgetRandomColor(this.args['X'].length); if (args['lineWidth']==null) this.args['lineWidth'] = 1; if (args['xDescript']==null) this.args['xDescript'] = "x"; if (args['yDescript']==null) this.args['yDescript'] = "y"; if (args['xGrid']==null) this.args['xGrid'] = false; if (args['yGrid']==null) this.args['yGrid'] = false; if (args['legendOuterBox']==null) this.args['legendOuterBox'] = true; this.eles = new Array(); } /** * calculate the median of an array * @function * @param {Array(double)} Y - the data to be calculate */ function DVMedian(X) { Y = X.slice(0); Y.sort(); if (Y.length%2==1) return Y[Math.floor(Y.length/2)]; return (Y[Math.floor(Y.length/2)]+Y[Math.floor(Y.length/2)-1])*1.0/2; } /** * calculate the needed value for each box * @function * @param {Array(double)} Y - an array of double.the data needed statistic. * @return {Object} staValue - the value returns * @return {double} staValue.median - the median of Y * @return {double} staValue.upperQuartile - the upper quartile of Y * @return {double} staValue.lowerQuartile - the lower quartile of Y * @return {double} staValue.upperBound - the upper Bound of Y * @return {double} staValue.lowerBound - the lower Bound of Y * @return {Array(double)} staValue.outlier - the outlier bound for the Y,[min,max] */ DVBoxChart.prototype.statistic = function(Y) { if (Y.length==0) return null; staValue = {}; Y.sort(function(a,b) { return a - b; }); if (Y.length%2==1) { staValue.median = Y[Math.floor(Y.length/2)]; staValue.upperQuartile = DVMedian(Y.slice(Math.floor(Y.length/2)+1)); staValue.lowerQuartile = DVMedian(Y.slice(0,Math.floor(Y.length/2))); } else { staValue.median = (Y[Math.floor(Y.length/2)]+Y[Math.floor(Y.length/2)-1])*1.0/2; staValue.upperQuartile = DVMedian(Y.slice(Math.floor(Y.length/2))); staValue.lowerQuartile = DVMedian(Y.slice(0,Math.floor(Y.length/2))); } staValue.outlier = []; IQR = (staValue.upperQuartile - staValue.lowerQuartile)*1.0/2; staValue.outlier.push(staValue.median-3*IQR); staValue.outlier.push(staValue.median+3*IQR); staValue.upperBound = -1000000; staValue.lowerBound = 1000000; for (var i=0;i=staValue.outlier[0]) staValue.lowerBound = Math.min(staValue.lowerBound,Y[i]); if (Y[i]<=staValue.outlier[1]) { staValue.upperBound = Math.max(staValue.upperBound,Y[i]); } } return staValue; } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVBoxChart.prototype.prepare = function(dv) { tmpY = DV2dArrMinMax(this.args.Ys); if (this.args.style=='bar') dv.initial([0,this.args.X.length],tmpY); ySpan = DVGetSpan(dv.Ymargin) xSpan = 1; cord_arg = {'xGrid':this.args.xGrid,'yGrid':this.args.yGrid,'xDescript':this.args.xDescript,'yDescript':this.args.yDescript, 'xSpan':xSpan,'ySpan':ySpan,'xStyle':'class','classes':this.args.X} this.eles.push(new DVCoordinate(cord_arg)); for (var i=0;istaValue.outlier[1]) { dotxy = dv.xyTrans(i+0.5,this.args.Ys[i][j]); this.eles.push(new DVDot({'x':dotxy[0],'y':dotxy[1],'color':this.args.colors[i],'style':'bubble'})) } } } } /** * draw the DVBarChart on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVBoxChart.prototype.draw = function(dv) { if (this.eles.length==0) { this.prepare(dv); } for (var i=this.eles.length-1;i>=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a General Graph * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(string)} args.nodes - a series of string,indicate for each node's text actualy * @param {Array(Array())} args.edges - a series of tuple,which contain two index number for the edge.example[[0,1],[1,2]] * @param {Array(DVColor)=} [args.color = random] - the color of the node * @param {string=} [args.style='undirected'] - the graph style.'undirected' or 'directed' * @param {Object[]} [args.ColorPattern = empty] - the color pattern of lines,the element is [[DVColor1,indexs1,indexs2...],[DVColor2,indexs11,indexs12...]] */ function DVGraph(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['nodes']==null) this.args['nodes'] = []; if (args['edges']==null) this.args['edges'] = []; if (args['ColorPattern']==null) this.args['ColorPattern'] = {}; if (args['color']==null) this.args['color'] = DVgetRandomColor(1)[0]; if (args['style']==null || (args.style!="undirected" && args.style!="directed")) this.args['style'] = 'undirected'; this.eles = new Array(); } DVGraph.prototype.isLinked = function(i,j) { for (var k =0;k=bbx) basic = Math.PI; basic = basic + Math.atan((bby-eey)/(bbx-eex)); this.eles.push(new DVLine({'shadow':false,'beginX':eex+Math.cos(basic+theta)*r,'beginY':eey+Math.sin(basic+theta)*r, 'endX':eex,'endY':eey})) this.eles.push(new DVLine({'shadow':false,'beginX':eex+Math.cos(basic-theta)*r,'beginY':eey+Math.sin(basic-theta)*r, 'endX':eex,'endY':eey})) } } //this.rerange('y'); } /** * draw the Pie chart on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVGraph.prototype.draw = function(dv) { if (this.eles.length==0) { this.prepare(dv); } for (var i=this.eles.length-1;i>=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Dendrogram,which can show some combination rule for the data * @constructor * @param {Object[]} args - a array contain arguments below * @param {object[]} args.tree - a set indicate the tree you want to draw,the base element is string,for example:["A",["B","C"]] * @param {DVColor=} [args.color = DVgetRandomColor(1)[0]] - the color for bubble * @param {string=} [args.style='bubble'] - the tree base element style,'bubble' or 'text' */ function DVDendrogram(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['tree']==null) this.args['tree'] = []; if (args['color']==null) this.args['color'] = DVgetRandomColor(1)[0]; if (args['style']==null || (args.style!="bubble" && args.style!="text")) this.args['style'] = 'bubble'; this.eles = new Array(); this.baseEleCount = 0; this.baseIndex = 0; } /** * recurrence prepare the needed elements * @function * @param {DVisual} dv - the Dvisual instance you want to draw * @param {elements} tree - the tree you want to draw,can be string at the node,otherwise object * @param {DVisual} level - the level of this procedure * @return {object} - return the width and base level from the bottom,[double,int] */ DVDendrogram.prototype.recurrencePrepare = function(dv,tree,level) { if (typeof(tree)=="object") { var children = new Array(); var levels = new Array(); for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Dendrogram,which can show some combination rule for the data * @constructor * @param {Object[]} args - a array contain arguments below * @param {Object[]} args.nodes - indicate a set of nodes,the elements is a string. * @param {Object[]} args.edges - indicate a set of edges,the elements is a tuple with two index,eg: [[0,1]] means an edge connect 0-th node and 1-th node * @param {Object=} [args.edgesValue = empty] - can be empty,to change the curve's width to show more infomation * @param {DVColor=} [args.CurveColor = DVgetRandomColor(1)[0]] - the Curve's Color * @param {DVColor=} [args.NodeColor = new DVColor()] - the Node's Color * @param {string=} [args.style='bubble'] - the node element style,'bubble' or 'text' * @param {boolean=} [args.bubble = true] - whether add a bubble to each node * @param {int=} [args.bubbleRadius = 2] - the radius of the added bubble * @param {double=} [args.lineWidth = 2] - the lineWidth of curve,when the edgesValue is not empty,lineWidth indicate the maxium Curve Width. */ function DVCircleConnectChart(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['nodes']==null) this.args['nodes'] = []; if (args['edges']==null) this.args['edges'] = []; if (args['edgesValue']==null) this.args['edgesValue'] = []; if (args['NodeColor']==null) this.args['NodeColor'] = new DVColor(); if (args['CurveColor']==null) this.args['CurveColor'] = DVgetRandomColor(1)[0]; if (args['bubble']==null) this.args['bubble'] = true; if (args['bubbleRadius']==null) this.args['bubbleRadius'] = 2; if (args['lineWidth']==null) this.args['lineWidth'] = 2; this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVCircleConnectChart.prototype.prepare = function(dv) { R = (Math.min(dv.oldHeight,dv.oldWidth) - 70)/2; mid = Math.min(dv.oldHeight,dv.oldWidth)/2; addang = Math.asin(dv.ctx.measureText('D').width*1.0/2/R); nodelocation = [] angs = [] for (var i=0;iMath.PI) { ang = ang + Math.PI; } cpx = mid + Math.cos(ang)*R*(1-cp_ratio); cpy = mid + Math.sin(ang)*R*(1-cp_ratio); lineWidth = this.args.lineWidth; if (this.args.edgesValue.length>0) { if (this.args.edgesValue.length!=this.args.edges.length) { console.log("ERROR! in DVCircleConnectChart,the edgesValue's length is not the same as edges' length") break; } lineWidth = lineWidth * this.args.edgesValue[i]/this.args.edgesValue.max(); } this.eles.push(new DVCurve({'beginX':nodelocation[a][0],'beginY':nodelocation[a][1],'endX':nodelocation[b][0],'endY':nodelocation[b][1], 'cpx':cpx,'cpy':cpy,'color':curveColor,'lineWidth':lineWidth})); } } /** * draw the Dendrogram on dv's canvas * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVCircleConnectChart.prototype.draw = function(dv) { if (this.eles.length==0) { this.prepare(dv); } //for (var i=0;i=0;i--) this.eles[i].draw(dv); } /** * A DVisual graph element indicate a Parallel coordinate * @constructor * @param {Object[]} args - a array contain arguments below * @param {Array(Array(double))} args.Xs - the set of multiple series nodes' x value,the length of Xs is the instance's number you want to draw,the elements' length is same with the arguments' length * @param {Array(string)} args.arguments - the arguments' name * @param {DVColor=} [args.color = new DVColor(100,100,100,0.3)] - the lines' default color,the more color optional can be configured in ColorPattern arguments * @param {Object[]} [args.ColorPattern = empty] - the color pattern of lines,the element is [[DVColor1,indexs1,indexs2...],[DVColor2,indexs11,indexs12...]] */ function DVParallelCoordinate(args) { if (arguments.length==0) args = {}; this.args = DVClone(args); if (args['Xs']==null) this.args['Xs'] = []; if (args['arguments']==null) this.args['arguments'] = []; if (args['classes']==null) this.args['classes'] = []; if (args['style']==null) this.args['style'] = 'dot|line'; if (args['color']==null) this.args['color'] = new DVColor(100,100,100,0.3); if (args['ColorPattern']==null) this.args['ColorPattern'] = {}; if (args['xGrid']==null) this.args['xGrid'] = true; if (args['yGrid']==null) this.args['yGrid'] = true; if (args['lineWidth']==null) this.args['lineWidth'] = 1; this.eles = new Array(); } /** * prepare the needed elements on the first time to draw it * @function * @param {DVisual} dv - the Dvisual instance you want to draw */ DVParallelCoordinate.prototype.prepare = function(dv) { coordinate = (dv.oldWidth*1.0)/(this.args.arguments.length); yupper = 20; ybottom = dv.oldHeight - 30; var ydrawMargin = ybottom - yupper; var maxx = []; var minn = []; var colors = []; for (var i =0;i=0;i--) this.eles[i].draw(dv); }