HTML5技术

js封装成插件-------Canvas统计图插件编写 - 蒋世超

字号+ 作者:H5之家 来源:H5之家 2017-09-12 09:00 我要评论( )

之前就说过,我想写一个canvas画统计图的插件,现在写好了 先说下实现的功能吧: 1.可以通过自定义X轴坐标属性和Y轴坐标属性按比例画出统计图 2.可以选择画折现图还是柱形统计图,或者两者都实现 3.可以自由定义折现颜色,坐标颜色,柱形图颜色 和canvas边框

之前就说过,我想写一个canvas画统计图的插件,现在写好了

先说下实现的功能吧:

  1.可以通过自定义X轴坐标属性和Y轴坐标属性按比例画出统计图

  2.可以选择画折现图还是柱形统计图,或者两者都实现

  3.可以自由定义折现颜色,坐标颜色,柱形图颜色 和canvas边框颜色,当然边框你也可以选择要或者不要

  4.可以选择是否实现柱形图和折现图的动画实现

实现过程

画坐标——画箭头——做X轴和Y轴的标注——画柱形图——画折现图

1 (function(window,document){ 2 var ChartDraws = function(options){ 3 if(!(this instanceof ChartDraws))return new ChartDraws(options); 4 this.options = $.extend({ 5 //报表所需的参数 6 "containerId" : "", //canvas所在容器id 7 "canvasWidth" : 400, 8 "canvasHeight" : 300, 9 "paddingLeft" : 20, 10 "paddingTop" : 20, 11 "columnChartData" :[], //柱形图的数量和对应得名称以及百分比 12 "yChartData" :[], //y轴的数量及名称 13 "axisColor" : "white", //坐标轴颜色 14 "columnChartColor" : "#EEE685", //柱形图颜色 15 "isNeedAnimation" : true, //是否需要动画 16 "isNeedLineChart" : true, //是否需要折线图 17 "isNeedColumnChart" : true, //是否需要柱形图 18 "lineChartColor" : "#90EE90", //折线图颜色,当isNeedLineChart=true时有效 19 "isNeedBorder" : false, //canvas是否需要外边框 20 "borderColor" : "white" //外边框颜色 21 },options); 22 if(this.options.canvasWidth<=500) 23 { 24 this.axisBorderWidth = 3; 25 this.fontSize = 8; 26 } 27 else if(this.options.canvasWidth<=800){ 28 this.axisBorderWidth = 4; 29 this.fontSize = 12; 30 } 31 else{ 32 this.axisBorderWidth = 5; 33 this.fontSize = 16; 34 } 35 var self = this; 36 _init(); 37 function _init(){ 38 var canvasDom = document.createElement("canvas"); 39 canvasDom.id = self.options.containerId+"_"+"canvas"; 40 canvasDom.width = self.options.canvasWidth; 41 canvasDom.height = self.options.canvasHeight; 42 if(self.options.isNeedBorder){ 43 canvasDom.style.borderWidth = 1; ; 45 canvasDom.style.borderColor = self.options.borderColor; 46 } 47 document.getElementById(self.options.containerId).appendChild(canvasDom); 48 self.context = document.getElementById(self.options.containerId+"_"+"canvas"); 49 self.ctx = self.context.getContext("2d"); 50 _drawAxis(); 51 } 52 53 function _drawAxis(){ [{x:self.options.paddingLeft,y:self.options.canvasHeight-self.options.paddingTop},{x:self.options.paddingLeft,y:self.options.paddingTop},{x:self.options.canvasWidth-self.options.paddingLeft,y:self.options.paddingTop}]); 55 self.ctx.strokeStyle=self.options.axisColor; 56 drawLine(self.ctx,XYData,self.axisBorderWidth); 57 //画三角箭头 58 //画y轴三角箭头 59 drawLine(self.ctx,transformAxis([{x:self.options.paddingLeft-self.axisBorderWidth,y:self.options.canvasHeight-self.options.paddingTop-self.axisBorderWidth*2},{x:self.options.paddingLeft,y:self.options.canvasHeight-self.options.paddingTop},{x:self.options.paddingLeft+self.axisBorderWidth,y:self.options.canvasHeight-self.options.paddingTop-self.axisBorderWidth*2}]),self.axisBorderWidth); 60 //画x轴三角箭头 61 drawLine(self.ctx,transformAxis([{x:self.options.canvasWidth-self.options.paddingLeft-self.axisBorderWidth*2,y:self.options.paddingTop+self.axisBorderWidth},{x:self.options.canvasWidth-self.options.paddingLeft,y:self.options.paddingTop},{x:self.options.canvasWidth-self.options.paddingLeft-self.axisBorderWidth*2,y:self.options.paddingTop-self.axisBorderWidth}]),self.axisBorderWidth); 62 _drawCoordinatePoints(); 63 } 64 65 function _drawCoordinatePoints(){ 66 self.reactAngleWidth = (1-2*0.04)*(self.options.canvasWidth-(2*self.options.paddingLeft))/(self.options.columnChartData.length*2-1); 67 self.lineDataList = []; 68 for(var i = 0;i<self.options.columnChartData.length;i++) 69 { 70 drawXText(self.ctx,2*self.options.columnChartData[i].NO*self.reactAngleWidth+self.options.paddingLeft+0.04*(self.options.canvasWidth-(2*self.options.paddingLeft))+self.reactAngleWidth/2,self.options.paddingTop/2,self.options.columnChartData[i].Name); 71 self.lineDataList.push({ 72 x:2*self.options.columnChartData[i].NO*self.reactAngleWidth+self.options.paddingLeft+0.04*(self.options.canvasWidth-(2*self.options.paddingLeft))+self.reactAngleWidth/2, 73 y:self.options.canvasHeight-(self.options.paddingTop+(self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[i].PT) 74 }) 75 } 76 77 //画Y轴title 画y轴虚线 78 self.reactAngleHeight = (self.options.canvasHeight-2*self.options.paddingTop)/(self.options.yChartData.length+1); 79 for(var j = 0;j<self.options.yChartData.length;j++) 80 { 81 drawYText(self.ctx,3*self.options.paddingLeft/4,self.options.paddingTop+self.reactAngleHeight*(j+1),self.options.yChartData[j].Name); 82 //画虚线 83 drawDottedLine(self.ctx,self.options.paddingLeft,self.options.paddingTop+self.reactAngleHeight*(j+1),self.options.canvasWidth-self.options.paddingLeft,self.options.paddingTop+self.reactAngleHeight*(j+1),self.options.canvasWidth-2*self.options.paddingLeft,10,self.axisBorderWidth/2); 84 } 85 _drawColumnChart(); 86 } 87 88 function _drawColumnChart(){ 89 //柱形图循环 90 var reactAngleTimer = 1; 91 function loopColumnChart() 92 { 93 var columnChartLooped = window.requestAnimationFrame(loopColumnChart); 94 if(reactAngleTimer<=100) 95 { 96 for(var k=0;k<self.options.columnChartData.length;k++) 97 { 98 self.ctx.fillStyle =self.options.columnChartColor; 99 drawRectangle(self.ctx,self.lineDataList[k].x-self.reactAngleWidth/2,self.options.canvasHeight-((self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[k].PT*reactAngleTimer/100+self.options.paddingTop),self.reactAngleWidth,(self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[k].PT*reactAngleTimer/100); 100 } 101 reactAngleTimer++; 102 } 103 else 104 { 105 window.cancelAnimationFrame(columnChartLooped); 106 columnChartLooped = null; 107 reactAngleTimer = 1; 108 if(self.options.isNeedLineChart) 109 { 110 loopLineChart(); 111 } 112 } 113 } 114 //折线图循环 115 var lineTimer = 0; 116 function loopLineChart() 117 { 118 var lineChartLooped = window.requestAnimationFrame(loopLineChart); 119 if(lineTimer<self.lineDataList.length-1) 120 { 121 self.ctx.lineWidth = 2*self.axisBorderWidth/3; 0) 123 { 124 drawCircle(self.ctx,self.lineDataList[lineTimer].x,self.lineDataList[lineTimer].y); 125 } 126 drawCircle(self.ctx,self.lineDataList[lineTimer+1].x,self.lineDataList[lineTimer+1].y); 127 self.ctx.beginPath(); 128 self.ctx.moveTo(self.lineDataList[lineTimer].x,self.lineDataList[lineTimer].y); 129 self.ctx.lineTo(self.lineDataList[lineTimer+1].x,self.lineDataList[lineTimer+1].y); 130 self.ctx.strokeStyle = self.options.lineChartColor; 131 self.ctx.lineWidth = 2*self.axisBorderWidth/3; 132 self.ctx.stroke(); 133 lineTimer++; 134 } 135 else 136 { 137 window.cancelAnimationFrame(lineChartLooped); 138 lineChartLooped = null; 139 lineTimer = 0; 140 } 141 } 142 //画柱形图 143 function drawRectangle(context,x,y,width,height){ 144 context.beginPath(); 145 context.fillRect(x,y,width,height); 146 } 147 //画圆 148 function drawCircle(context,x,y){ 149 context.beginPath(); 150 context.arc(x,y,self.axisBorderWidth/2,0,2*Math.PI,true); 151 context.strokeStyle=self.options.lineChartColor; 152 context.stroke(); 153 context.closePath(); 154 } 155 if(self.options.isNeedAnimation) 156 { 157 if(self.options.isNeedColumnChart) 158 { 159 loopColumnChart(); 160 } 161 else 162 { 163 if(self.options.isNeedLineChart) { 164 loopLineChart(); 165 } 166 } 167 } 168 else 169 { 170 if(self.options.isNeedColumnChart) 171 { 172 for(var k=0;k<self.options.columnChartData.length;k++) 173 { 174 self.ctx.fillStyle =self.options.columnChartColor; 175 drawRectangle(self.ctx,self.lineDataList[k].x-self.reactAngleWidth/2,self.options.canvasHeight-((self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[k].PT+self.options.paddingTop),self.reactAngleWidth,(self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[k].PT); 176 } 177 } 178 if(self.options.isNeedLineChart) { l < self.lineDataList.length - 1; l++) { 180 self.ctx.lineWidth = 4; 0) { 182 drawCircle(self.ctx, self.lineDataList[l].x, self.lineDataList[l].y); 183 } 184 drawCircle(self.ctx, self.lineDataList[l + 1].x, self.lineDataList[l + 1].y); 185 self.ctx.beginPath(); 186 self.ctx.moveTo(self.lineDataList[l].x, self.lineDataList[l].y); 187 self.ctx.lineTo(self.lineDataList[l + 1].x, self.lineDataList[l + 1].y); 188 self.ctx.strokeStyle = self.options.lineChartColor; 189 self.ctx.lineWidth = 2*self.axisBorderWidth/3; 190 self.ctx.stroke(); 191 } 192 } 193 } 194 } function transformAxis(data) 198 { 199 var newData=[]; 200 for(var i=0;i<data.length;i++){ 201 newData.push({ 202 x:data[i].x, 203 y:self.options.canvasHeight-data[i].y 204 }) 205 } 206 return newData; 207 } 208 209 function drawLine(context,point,width){ 210 context.beginPath(); 211 context.moveTo(point[0].x,point[0].y); 2) 213 { 214 for(var i=1;i<point.length;i++) 215 { 216 context.lineTo(point[i].x,point[i].y); 217 } 218 } 219 context.lineWidth = width; 220 context.lineJoin='round'; 221 context.stroke(); 222 context.closePath(); 223 } 224 225 //画y轴title 226 function drawYText(context,x,y,str) { 227 context.beginPath(); Microsoft Yahei'.replace("{fontSize}",self.fontSize+"px"); 229 context.fillStyle = 'white'; 230 context.textAlign = 'right'; 231 context.fillText(str,x,self.options.canvasHeight-y); 232 context.closePath(); 233 } 234 //画x轴title 235 function drawXText(context,x,y,str) { 236 context.beginPath(); Microsoft Yahei'.replace("{fontSize}",self.fontSize+"px"); 238 context.fillStyle = 'white'; 239 context.textAlign = 'center'; 240 context.fillText(str,x,self.options.canvasHeight-y); 241 context.closePath(); 242 } 243 function drawDottedLine(context,x1,y1,x2,y2,totalLength,length,lineWidth){ 244 y1 = self.options.canvasHeight-y1; 245 y2 = self.options.canvasHeight-y2; undefined ? 5 : length; 247 //计算有多少个线段 248 context.beginPath(); 249 var num = Math.floor(totalLength/dashLen); 250 context.lineWidth = lineWidth; ; i < num; i++) 252 { ? 'moveTo' : 'lineTo'](x1+(x2-x1)/num*i,y1+(y2-y1)/num*i); 254 } 255 context.stroke(); 256 } 257 }; 258 window.ChartDraws = ChartDraws; 259 }(window,document)

话不多说,上代码

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 【前端技术】nodejs安装扩展插件,总是报错enoent的解决方案 - 星点design

    【前端技术】nodejs安装扩展插件,总是报错enoent的解决方案 - 星点d

    2017-09-10 08:01

  • AmazeUI(妹子UI)中CSS组件、JS插件、Web组件的区别 - 长沙游哥

    AmazeUI(妹子UI)中CSS组件、JS插件、Web组件的区别 - 长沙游哥

    2017-08-01 09:00

  • IDEA安装vue开发插件 - PC.aaron

    IDEA安装vue开发插件 - PC.aaron

    2017-07-14 08:05

  • 【干货】Chrome插件(扩展)开发全攻略 - 我是小茗同学

    【干货】Chrome插件(扩展)开发全攻略 - 我是小茗同学

    2017-07-12 13:00

网友点评