UNPKG

chartnew.js

Version:

Simple HTML5 Charts using the canvas element

516 lines (445 loc) 18.7 kB
var moreInChartData_default= { position : "INCHART", iter : "last", link : "Line", // default values for Line; linkStrokeColorLine: "black", linkStrokeStyleLine : "solid", linkStrokeSizeLine: 2, paddingValXLine : 4, paddingValYLine : 0, piePaddingY : 0.1, paddingX : 0, paddingY : 0, // default values for Triangle; arrowWidth : 2, arrowHeight : 0.1, // linkFillColorTriangle : null, linkStrokeColorTriangle: "rgba(0,0,0,0)", linkStrokeStyleTriangle : "solid", linkStrokeSizeTriangle: 0, paddingValXTriangle : 4, paddingValYTriangle : -16, // default for text; text : "<Value>", fontColor : "black", fontStyle : "normal", fontSize : 25, fontFamily : "'Arial'", // default for Image; imageLoad : null, imagePos : 1, // 0 before text, 1 after text; imageWidth : 20, imageHeight: 20, spaceBetweenTextAndImage : 5, // relativeImagePosition : "smart", // rotate : 0, // Point position; limitToChart : false, x1 : null, y1 : null, x2 : null, y2 : null, x3 : null, y3 : null, x4 : null, y4 : null, x5 : null, y5 : null, x6 : null, y6 : null, x7 : null, y7 : null, x8 : null, y8 : null, x9 : null, y9 : null, x10 : null, y10 : null, paddingX1 : null, paddingY1 : null, paddingX2 : null, paddingY2 : null, paddingX3 : null, paddingY3 : null, paddingX4 : null, paddingY4 : null, paddingX5 : null, paddingY5 : null, paddingX6 : null, paddingY6 : null, paddingX7 : null, paddingY7 : null, paddingX8 : null, paddingY8 : null, paddingX9 : null, paddingY9 : null, paddingX10 : null, paddingY10 : null, // Special values; avoidOverwrite : true }; function pushInGraphData(type_chart,data,config,pushInfoDefault) { var pushconfig = (pushInfoDefault) ? mergeChartConfig(moreInChartData_default, pushInfoDefault) : moreInChartData_default; var resconfig; var pushInfo,shapesInChart; if(typeof data.datasets == "object") { pushInfo=data.datasets; if(typeof data.shapesInChart == "undefined") data.shapesInChart=[]; shapesInChart=data.shapesInChart; for (var i=0;i<data.datasets.length;i++){ for(var j=0;j<data.datasets[i].data.length;j++) { if(typeof data.datasets[i].data[j]!="undefined") { resconfig = mergeChartConfig(data.datasets[i], pushconfig); pushInGraphDataSub(type_chart.toUpperCase(),data.datasets[i],i,j,shapesInChart,data,config,resconfig); } } } data.shapesInChart[0].avoidOverwrite=pushconfig.avoidOverwrite; } else { pushInfo=data; if(typeof data[0].shapesInChart == "undefined") data[0].shapesInChart=[]; shapesInChart=data[0].shapesInChart; for (var i=0;i<data.length;i++){ if(typeof data[i].value !="undefined") { resconfig = mergeChartConfig(data[i], pushconfig); pushInGraphDataSub(type_chart.toUpperCase(),data[i],i,-1,shapesInChart,data,config,resconfig); } } data[0].shapesInChart[0].avoidOverwrite=pushconfig.avoidOverwrite; } function mergeOptionConfig(defaults, userDefined,posj) { var returnObj = {}; for (var attrname in defaults) { returnObj[attrname] = defaults[attrname]; } for (var attrnameBis in userDefined) { if(typeof userDefined[attrnameBis]=="object") returnObj[attrnameBis] = userDefined[attrnameBis][Math.min(j,userDefined[attrnameBis].length-1)]; else returnObj[attrnameBis] = userDefined[attrnameBis]; } return returnObj; }; function pushInGraphDataSub(type_chart,pushInfoI,i,j,shapesInChart,data,config,resconfig) { var addRadius; shapesInChart[shapesInChart.length]=mergeOptionConfig(resconfig,pushInfoI,j); // push shapesInChart info for the pointer; var newShapes=shapesInChart[shapesInChart.length-1]; if (newShapes.text.indexOf("<Title>") >= 0) newShapes.text=newShapes.text.replace(/<Title>/g,pushInfoI.title); if (newShapes.text.indexOf("<Value>") >= 0){ if(j==-1)newShapes.text=newShapes.text.replace(/<Value>/g,""+pushInfoI.value); else newShapes.text=newShapes.text.replace(/<Value>/g,""+pushInfoI.data[j]); } if (newShapes.text.indexOf("<i>") >= 0) newShapes.text=newShapes.text.replace(/<i>/g,i); if (newShapes.text.indexOf("<j>") >= 0) newShapes.text=newShapes.text.replace(/<j>/g,j); switch(newShapes.link.toUpperCase()) { case "TRIANGLE" : var cumval=0; if(typeof data.length!="undefined") { for(var vi=0;vi<data.length;vi++){ if(data[vi].value>0)cumval=cumval+1*data[vi].value; } } else { for(var vi=0;vi<data.datasets.length;vi++){ if(data.datasets[vi].data[j]>0)cumval=cumval+1*data.datasets[vi].data[j]; } } var arrowWidth=(cumval/360)*newShapes.arrowWidth; newShapes.shape = annotateTriangleFunction; newShapes.strokeColor=newShapes.linkStrokeColorLine; newShapes.strokeStyle=newShapes.linkStrokeStyleLine; newShapes.strokeSize=newShapes.linkStrokeSizeLine; switch(type_chart) { case "DELPIE" : case "DELDOUGHNUT" : var multRadius; var percentageInnerCutout=50; if(typeof config.percentageInnerCutout != "undefined")percentageInnerCutout=config.percentageInnerCutout; if(type_chart.toUpperCase()=="DOUGHNUT" || type_chart.toUpperCase()=="MDOUGHNUT")multRadius=100/(100-percentageInnerCutout); else multRadius=1; addRadius=0; if(typeof pushInfoI.expandOutRadius!="undefined")addRadius=1*pushInfoI.expandOutRadius; if(newShapes.x1==null)newShapes.x1= (pushInfoI.data[j]==0 ? i : Math.max(i-0.5,i-(arrowWidth/pushInfoI.data[j]))); if(newShapes.y1==null)newShapes.y1= 0.99+addRadius; if(newShapes.x2==null)newShapes.x2= i; if(newShapes.y2==null)newShapes.y2 =1+newShapes.arrowHeight+addRadius; if(newShapes.x3==null)newShapes.x3= (pushInfoI.data[j]==0 ? i : Math.min(i+0.5,i+(arrowWidth/pushInfoI.data[j]))); if(newShapes.y3==null)newShapes.y3 = 0.99+addRadius; if(newShapes.x4==null)newShapes.x4 = i; if(newShapes.y4==null)newShapes.y4 = 1.2+addRadius; if(newShapes.fillColor==null)newShapes.fillColor =pushInfoI.color; break; case "PIE" : case "DOUGHNUT" : case "MPIE" : case "MDOUGHNUT" : var multRadius; var percentageInnerCutout=50; if(typeof config.percentageInnerCutout != "undefined")percentageInnerCutout=config.percentageInnerCutout; if(type_chart.toUpperCase()=="MDOUGHNUT")multRadius=100/(100-percentageInnerCutout); else multRadius=1; addRadius=0; if(typeof pushInfoI.expandOutRadius!="undefined")addRadius=1*pushInfoI.expandOutRadius; if(newShapes.x1==null)newShapes.x1= (pushInfoI.data[j]==0 ? i : Math.max(i-0.5,i-(arrowWidth/pushInfoI.data[j]))); if(newShapes.y1==null)newShapes.y1= 0.99+addRadius; if(newShapes.x2==null)newShapes.x2= i; if(newShapes.y2==null)newShapes.y2 =1+newShapes.arrowHeight+addRadius; if(newShapes.x3==null)newShapes.x3= (pushInfoI.data[j]==0 ? i : Math.min(i+0.5,i+(arrowWidth/pushInfoI.data[j]))); if(newShapes.y3==null)newShapes.y3 = 0.99+addRadius; if(newShapes.x4==null)newShapes.x4 = i; if(newShapes.y4==null)newShapes.y4 = 1.2+addRadius; if(newShapes.posj==null)newShapes.posj = j; if(newShapes.fillColor==null)newShapes.fillColor =pushInfoI.fillColor; break; case "POLARAREA" : case "LINE" : case "RADAR" : case "BAR" : case "HORIZONTALBAR" : case "STACKEDBAR" : case "HORIZONTALSTACKEDBAR" : // not implemented; break; }; break; case "LINE" : default: newShapes.shape = annotateLineFunction; newShapes.strokeColor=newShapes.linkStrokeColorLine; newShapes.strokeStyle=newShapes.linkStrokeStyleLine; newShapes.strokeSize=newShapes.linkStrokeSizeLine; switch(type_chart) { case "PIE" : case "DOUGHNUT" : case "MPIE" : case "MDOUGHNUT" : var multRadius; var percentageInnerCutout=50; if(typeof config.percentageInnerCutout != "undefined")percentageInnerCutout=config.percentageInnerCutout; if(type_chart.toUpperCase()=="MDOUGHNUT")multRadius=100/(100-percentageInnerCutout); else multRadius=1; addRadius=0; if(typeof pushInfoI.expandOutRadius!="undefined")addRadius=1*pushInfoI.expandOutRadius; if(newShapes.x1==null)newShapes.x1=i; if(newShapes.y1==null)newShapes.y1=1+addRadius; if(newShapes.x2==null)newShapes.x2=i; if(newShapes.y2==null)newShapes.y2=1+newShapes.piePaddingY*multRadius; // x10=center of circle; if(newShapes.x10==null)newShapes.x10=i; if(newShapes.y10==null)newShapes.y10=-999; if(newShapes.posj==null)newShapes.posj = j; break; case "DELPIE" : case "DELDOUGHNUT" : var multRadius; var percentageInnerCutout=50; if(typeof config.percentageInnerCutout != "undefined")percentageInnerCutout=config.percentageInnerCutout; if(type_chart.toUpperCase()=="DOUGHNUT" || type_chart.toUpperCase()=="DOUGHNUT")multRadius=100/(100-percentageInnerCutout); else multRadius=1; addRadius=0; if(typeof pushInfoI.expandOutRadius!="undefined")addRadius=1*pushInfoI.expandOutRadius; if(newShapes.x1==null)newShapes.x1=i; if(newShapes.y1==null)newShapes.y1=1+addRadius; if(newShapes.x2==null)newShapes.x2=i; if(newShapes.y2==null)newShapes.y2=1+newShapes.piePaddingY*multRadius; if(newShapes.x10==null)newShapes.x10=i; if(newShapes.y10==null)newShapes.y10=1-multRadius; break; case "POLARAREA" : case "LINE" : case "RADAR" : case "BAR" : case "HORIZONTALBAR" : case "STACKEDBAR" : case "HORIZONTALSTACKEDBAR" : // not implemented; break; }; break; } // push shapesInChart info for the text and Image; } ; }; function annotateLineFunction(area, ctx, data, statData, posi,posj,othervars){ if (typeof ctx.specialInChartData=="undefined"){ ctx.specialInChartData=[]; ctx.specialInChartData.prevMsr=[]; ctx.specialInChartData.textAlign=[]; ctx.specialInChartData.textBaseline=[]; ctx.specialInChartData.prevXln=[]; ctx.specialInChartData.prevYln=[]; } /* compute radius */ var radius= (Math.sqrt(Math.pow(othervars.xypos2.xpos-othervars.xypos10.xpos,2)+ Math.pow(othervars.xypos2.ypos-othervars.xypos10.ypos,2))); var xln, yln; var xip, yip; var paddingX, paddingY; var paddingValX=othervars.shapesInChart.paddingValXLine; var paddingValY=othervars.shapesInChart.paddingValYLine; // line to label; ctx.beginPath(); xip=othervars.xypos2.xpos; yip=othervars.xypos2.ypos; if(othervars.xypos10.xpos>othervars.xypos2.xpos) { ctx.textAlign="right"; paddingX=-paddingValX; xln=othervars.xypos10.xpos-radius+othervars.shapesInChart.paddingX; yln=othervars.xypos2.ypos+othervars.shapesInChart.paddingY; } else { ctx.textAlign="left"; paddingX=paddingValX; xln=radius + othervars.xypos10.xpos+othervars.shapesInChart.paddingX; yln=othervars.xypos2.ypos+othervars.shapesInChart.paddingY; } var avoidOverwrite; if(typeof data.length!="undefined")avoidOverwrite=data[0].shapesInChart[0].avoidOverwrite; else avoidOverwrite=data.shapesInChart[0].avoidOverwrite; if (typeof ctx.specialInChartData.prevYln=="undefined") { ctx.specialInChartData.prevXln=[]; ctx.specialInChartData.prevYln=[]; } if(avoidOverwrite) { if (typeof ctx.specialInChartData.prevYln[othervars.posj]!="undefined") { if(Math.abs(ctx.specialInChartData.prevYln[othervars.posj]-yln)<1.5*othervars.shapesInChart.fontSize) { if(othervars.xypos10.xpos<othervars.xypos2.xpos)yln=Math.max(yln,ctx.specialInChartData.prevYln[othervars.posj]+1.5*othervars.shapesInChart.fontSize); else yln=Math.min(yln,ctx.specialInChartData.prevYln[othervars.posj]-1.5*othervars.shapesInChart.fontSize); } }; ctx.specialInChartData.prevXln[othervars.posj]=xln; ctx.specialInChartData.prevYln[othervars.posj]=yln; }; ctx.beginPath(); ctx.moveTo(othervars.xypos1.xpos, othervars.xypos1.ypos); ctx.quadraticCurveTo(xip, yip,xln, yln); ctx.lineWidth = othervars.shapesInChart.strokeSize; ctx.strokeStyle = othervars.shapesInChart.strokeColor; ctx.setLineDash(lineStyleFn(othervars.shapesInChart.strokeStyle)); ctx.stroke(); // set text/shape position; ctx.beginPath(); ctx.textBaseline="middle"; if(othervars.xypos2.ypos<othervars.xypos1.ypos) { paddingY=-paddingValY; } else { paddingY=1*paddingValY; } // draw labels/images; drawTextAndImage(area, ctx, data,statData, posi,posj,othervars,xln+paddingX, yln+paddingY); }; function annotateTriangleFunction(area, ctx, data,statData, posi,posj,othervars){ if (typeof ctx.specialInChartData=="undefined"){ ctx.specialInChartData=[]; ctx.specialInChartData.prevMsr=[]; ctx.specialInChartData.textAlign=[]; ctx.specialInChartData.textBaseline=[]; ctx.specialInChartData.prevXln=[]; ctx.specialInChartData.prevYln=[]; } // triangle to label; ctx.beginPath(); if(othervars.xypos1.xpos==othervars.xypos3.xpos && othervars.xypos1.ypos==othervars.xypos3.ypos) { ctx.strokeStyle = othervars.shapesInChart.fillColor; ctx.lineWidth = 2; ctx.moveTo(othervars.xypos1.xpos, othervars.xypos1.ypos); ctx.lineTo(othervars.xypos2.xpos, othervars.xypos2.ypos); } else { ctx.moveTo(othervars.xypos1.xpos, othervars.xypos1.ypos); ctx.lineWidth = 0; ctx.strokeStyle = "rgba(0,0,0,0)"; ctx.lineTo(othervars.xypos2.xpos, othervars.xypos2.ypos); ctx.lineTo(othervars.xypos3.xpos, othervars.xypos3.ypos); ctx.closePath(); ctx.fillStyle=othervars.shapesInChart.fillColor; ctx.fill(); } ctx.stroke(); // set Label/image position; var paddingX=0; var paddingY=0; var paddingValX=othervars.shapesInChart.paddingValXTriangle; var paddingValY=othervars.shapesInChart.paddingValYTriangle; var xln=othervars.xypos4.xpos; var yln=othervars.xypos4.ypos; ctx.beginPath(); if(othervars.xypos4.xpos>=othervars.xypos2.xpos) { paddingX=paddingValX; ctx.textAlign="left"; } else { paddingX=-paddingValX; ctx.textAlign="right"; } ctx.textBaseline="middle"; var avoidOverwrite; if(typeof data.length!="undefined")avoidOverwrite=data[0].shapesInChart[0].avoidOverwrite; else avoidOverwrite=data.shapesInChart[0].avoidOverwrite; if(avoidOverwrite) { if (typeof ctx.specialInChartData.prevYln[othervars.posj]!="undefined" && ctx.textAlign==ctx.specialInChartData.textAlign[othervars.posj]) { if(othervars.xypos4.xpos>=othervars.xypos2.xpos) { yln=Math.max(yln,ctx.specialInChartData.prevYln[othervars.posj]+1.5*othervars.shapesInChart.fontSize); } else { yln=Math.min(yln,ctx.specialInChartData.prevYln[othervars.posj]-1.5*othervars.shapesInChart.fontSize); } } ctx.specialInChartData.prevXln[othervars.posj]=xln; ctx.specialInChartData.prevYln[othervars.posj]=yln; }; // draw labels/images; ctx.specialInChartData.prevMsr[othervars.posj]=drawTextAndImage(area, ctx, data,statData, posi,posj,othervars,xln+paddingX, yln+paddingY); ctx.specialInChartData.textAlign[othervars.posj]=ctx.textAlign; ctx.specialInChartData.textBaseline[othervars.posj]=ctx.textBaseline; }; function drawTextAndImage(area, ctx, data,statData, posi,posj,othervars,xpos,ypos) { var paddingTextX=0; var paddingTextY=0; var paddingImageX=0; var paddingImageY=0; var lgt=0; var hgt=0; var txtSize=0; // compute padding values; if(othervars.shapesInChart.imageLoad != null && othervars.shapesInChart.text != "") { ctx.save(); var fontSize=othervars.shapesInChart.fontSize; ctx.font = othervars.shapesInChart.fontStyle + " " + othervars.shapesInChart.fontSize.toString() + "px " + othervars.shapesInChart.fontFamily; ctx.fillStyle = othervars.shapesInChart.fontColor; txtSize=ctx.measureTextMultiLine(othervars.shapesInChart.text,othervars.shapesInChart.fontSize); if(othervars.shapesInChart.imagePos==1 && ctx.textAlign=="right") { paddingTextX=-(othervars.shapesInChart.imageWidth+othervars.shapesInChart.spaceBetweenTextAndImage); paddingImageX=-(othervars.shapesInChart.imageWidth); } else if(othervars.shapesInChart.imagePos==0 && ctx.textAlign=="left") { paddingTextX=othervars.shapesInChart.imageWidth+othervars.shapesInChart.spaceBetweenTextAndImage; } else if(othervars.shapesInChart.imagePos==0 && ctx.textAlign=="right") { paddingImageX=-(txtSize.textWidth+othervars.shapesInChart.spaceBetweenTextAndImage+othervars.shapesInChart.imageWidth); } else if(othervars.shapesInChart.imagePos==1 && ctx.textAlign=="left") { paddingImageX=txtSize.textWidth+othervars.shapesInChart.spaceBetweenTextAndImage; } ctx.restore(); lgt=othervars.shapesInChart.spaceBetweenTextAndImage; }; // draw text; if(othervars.shapesInChart.text!="") { ctx.save(); ctx.translate(xpos+paddingTextX,ypos+paddingTextY); var fontSize=othervars.shapesInChart.fontSize; ctx.font = othervars.shapesInChart.fontStyle + " " + othervars.shapesInChart.fontSize.toString() + "px " + othervars.shapesInChart.fontFamily; ctx.fillStyle = othervars.shapesInChart.fontColor; if (othervars.shapesInChart.iter !=="all" || (othervars.shapesInChart.iter === "all" && othervars.cntiter != othervars.config.animationSteps) || othervars.config.animation==false) { ctx.fillTextMultiLine(othervars.shapesInChart.text, 0, 0, ctx.textBaseline, Math.ceil(ctx.chartTextScale*fontSize),true,othervars.config.detectMouseOnText,ctx,"SHAPESINCHART_TEXTMOUSE",0,xpos+paddingTextX,ypos+paddingTextY,-1,-1); } else ctx.fillTextMultiLine(othervars.shapesInChart.text, 0, 0, ctx.textBaseline, Math.ceil(ctx.chartTextScale*fontSize),true,false,ctx,"SHAPESINCHART_TEXTMOUSE",0,xpos+paddingTextX,ypos+paddingTextY,-1,-1); ctx.restore(); lgt+=txtSize; hgt=Math.max(hgt,1.5* othervars.shapesInChart.fontSize); } // draw image; if(othervars.shapesInChart.imageLoad != null) { paddingImageY=-(othervars.shapesInChart.imageHeight-((2/3)*txtSize.textHeight/2)); ctx.save(); // ctx.translate(xpos+paddingImageX, ypos+paddingImageY -(othervars.shapesInChart.fontSize/2)+imageAfterPaddingY-(othervars.shapesInChart.imageAfterHeight/2)); ctx.translate(xpos+paddingImageX, ypos+paddingImageY); ctx.drawImage(othervars.shapesInChart.imageLoad, 0, 0,othervars.shapesInChart.imageLoad.width,othervars.shapesInChart.imageLoad.height,0, 0,othervars.shapesInChart.imageWidth,othervars.shapesInChart.imageHeight); ctx.restore(); lgt+=othervars.shapesInChart.imageWidth; hgt=Math.max(hgt,othervars.shapesInChart.imageWidth.imageHeight); } return {height : hgt,width : lgt}; };