下面小編就為大家帶來一篇js封裝成插件_Canvas統計圖外掛程式編寫實例。小編覺得挺不錯的,現在就分享js原始碼給大家,也給大家做個參考。對js有興趣的一起跟隨小編過來看看吧
之前就說過,我想寫一個canvas畫統計圖的插件,現在寫好了
先說下實現的功能吧:
1.可以透過自訂X軸座標屬性和Y軸座標屬性按比例畫出統計圖
2.可以選擇畫折現圖還是長條統計圖,或兩者都實現
3.可以自由定義折現顏色,座標顏色,長條圖顏色和canvas邊框顏色,當然邊框你也可以選擇要或不要
4.可以選擇是否實現長條圖和折現圖的動畫實作
##實作過程
#畫座標-畫箭頭-做X軸與Y軸的標註-畫長條圖-畫出折現圖
話不多說,上程式碼
(function(window,document){ var ChartDraws = function(options){ if(!(this instanceof ChartDraws))return new ChartDraws(options); this.options = $.extend({ //报表所需的参数 "containerId" : "", //canvas所在容器id "canvasWidth" : 400, "canvasHeight" : 300, "paddingLeft" : 20, "paddingTop" : 20, "columnChartData" :[], //柱形图的数量和对应得名称以及百分比 "yChartData" :[], //y轴的数量及名称 "axisColor" : "white", //坐标轴颜色 "columnChartColor" : "#EEE685", //柱形图颜色 "isNeedAnimation" : true, //是否需要动画 "isNeedLineChart" : true, //是否需要折线图 "isNeedColumnChart" : true, //是否需要柱形图 "lineChartColor" : "#90EE90", //折线图颜色,当isNeedLineChart=true时有效 "isNeedBorder" : false, //canvas是否需要外边框 "borderColor" : "white" //外边框颜色 },options); if(this.options.canvasWidth<=500) { this.axisBorderWidth = 3; this.fontSize = 8; } else if(this.options.canvasWidth<=800){ this.axisBorderWidth = 4; this.fontSize = 12; } else{ this.axisBorderWidth = 5; this.fontSize = 16; } var self = this; _init(); function _init(){ var canvasDom = document.createElement("canvas"); canvasDom.id = self.options.containerId+"_"+"canvas"; canvasDom.width = self.options.canvasWidth; canvasDom.height = self.options.canvasHeight; if(self.options.isNeedBorder){ canvasDom.style.borderWidth = 1; canvasDom.style.borderStyle = "solid"; canvasDom.style.borderColor = self.options.borderColor; } document.getElementById(self.options.containerId).appendChild(canvasDom); self.context = document.getElementById(self.options.containerId+"_"+"canvas"); self.ctx = self.context.getContext("2d"); _drawAxis(); } function _drawAxis(){ var XYData =transformAxis( [{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}]); self.ctx.strokeStyle=self.options.axisColor; drawLine(self.ctx,XYData,self.axisBorderWidth); //画三角箭头 //画y轴三角箭头 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); //画x轴三角箭头 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); _drawCoordinatePoints(); } function _drawCoordinatePoints(){ self.reactAngleWidth = (1-2*0.04)*(self.options.canvasWidth-(2*self.options.paddingLeft))/(self.options.columnChartData.length*2-1); self.lineDataList = []; for(var i = 0;i<self.options.columnChartData.length;i++) { 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); self.lineDataList.push({ x:2*self.options.columnChartData[i].NO*self.reactAngleWidth+self.options.paddingLeft+0.04*(self.options.canvasWidth-(2*self.options.paddingLeft))+self.reactAngleWidth/2, y:self.options.canvasHeight-(self.options.paddingTop+(self.options.canvasHeight-2*self.options.paddingTop)*self.options.columnChartData[i].PT) }) } //画Y轴title 画y轴虚线 self.reactAngleHeight = (self.options.canvasHeight-2*self.options.paddingTop)/(self.options.yChartData.length+1); for(var j = 0;j<self.options.yChartData.length;j++) { drawYText(self.ctx,3*self.options.paddingLeft/4,self.options.paddingTop+self.reactAngleHeight*(j+1),self.options.yChartData[j].Name); //画虚线 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); } _drawColumnChart(); } function _drawColumnChart(){ //柱形图循环 var reactAngleTimer = 1; function loopColumnChart() { var columnChartLooped = window.requestAnimationFrame(loopColumnChart); if(reactAngleTimer<=100) { for(var k=0;k<self.options.columnChartData.length;k++) { self.ctx.fillStyle =self.options.columnChartColor; 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); } reactAngleTimer++; } else { window.cancelAnimationFrame(columnChartLooped); columnChartLooped = null; reactAngleTimer = 1; if(self.options.isNeedLineChart) { loopLineChart(); } } } //折线图循环 var lineTimer = 0; function loopLineChart() { var lineChartLooped = window.requestAnimationFrame(loopLineChart); if(lineTimer<self.lineDataList.length-1) { self.ctx.lineWidth = 2*self.axisBorderWidth/3; if(lineTimer == 0) { drawCircle(self.ctx,self.lineDataList[lineTimer].x,self.lineDataList[lineTimer].y); } drawCircle(self.ctx,self.lineDataList[lineTimer+1].x,self.lineDataList[lineTimer+1].y); self.ctx.beginPath(); self.ctx.moveTo(self.lineDataList[lineTimer].x,self.lineDataList[lineTimer].y); self.ctx.lineTo(self.lineDataList[lineTimer+1].x,self.lineDataList[lineTimer+1].y); self.ctx.strokeStyle = self.options.lineChartColor; self.ctx.lineWidth = 2*self.axisBorderWidth/3; self.ctx.stroke(); lineTimer++; } else { window.cancelAnimationFrame(lineChartLooped); lineChartLooped = null; lineTimer = 0; } } //画柱形图 function drawRectangle(context,x,y,width,height){ context.beginPath(); context.fillRect(x,y,width,height); } //画圆 function drawCircle(context,x,y){ context.beginPath(); context.arc(x,y,self.axisBorderWidth/2,0,2*Math.PI,true); context.strokeStyle=self.options.lineChartColor; context.stroke(); context.closePath(); } if(self.options.isNeedAnimation) { if(self.options.isNeedColumnChart) { loopColumnChart(); } else { if(self.options.isNeedLineChart) { loopLineChart(); } } } else { if(self.options.isNeedColumnChart) { for(var k=0;k<self.options.columnChartData.length;k++) { self.ctx.fillStyle =self.options.columnChartColor; 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); } } if(self.options.isNeedLineChart) { for (var l = 0; l < self.lineDataList.length - 1; l++) { self.ctx.lineWidth = 4; if (l == 0) { drawCircle(self.ctx, self.lineDataList[l].x, self.lineDataList[l].y); } drawCircle(self.ctx, self.lineDataList[l + 1].x, self.lineDataList[l + 1].y); self.ctx.beginPath(); self.ctx.moveTo(self.lineDataList[l].x, self.lineDataList[l].y); self.ctx.lineTo(self.lineDataList[l + 1].x, self.lineDataList[l + 1].y); self.ctx.strokeStyle = self.options.lineChartColor; self.ctx.lineWidth = 2*self.axisBorderWidth/3; self.ctx.stroke(); } } } } function transformAxis(data) { var newData=[]; for(var i=0;i<data.length;i++){ newData.push({ x:data[i].x, y:self.options.canvasHeight-data[i].y }) } return newData; } function drawLine(context,point,width){ context.beginPath(); context.moveTo(point[0].x,point[0].y); if(point.length>2) { for(var i=1;i<point.length;i++) { context.lineTo(point[i].x,point[i].y); } } context.lineWidth = width; context.lineJoin='round'; context.stroke(); context.closePath(); } //画y轴title function drawYText(context,x,y,str) { context.beginPath(); context.font = '{fontSize} Microsoft Yahei'.replace("{fontSize}",self.fontSize+"px"); context.fillStyle = 'white'; context.textAlign = 'right'; context.fillText(str,x,self.options.canvasHeight-y); context.closePath(); } //画x轴title function drawXText(context,x,y,str) { context.beginPath(); context.font = '{fontSize} Microsoft Yahei'.replace("{fontSize}",self.fontSize+"px"); context.fillStyle = 'white'; context.textAlign = 'center'; context.fillText(str,x,self.options.canvasHeight-y); context.closePath(); } function drawDottedLine(context,x1,y1,x2,y2,totalLength,length,lineWidth){ y1 = self.options.canvasHeight-y1; y2 = self.options.canvasHeight-y2; var dashLen = length === undefined ? 5 : length; //计算有多少个线段 context.beginPath(); var num = Math.floor(totalLength/dashLen); context.lineWidth = lineWidth; for(var i = 0 ; i < num; i++) { context[i%2==0 ? 'moveTo' : 'lineTo'](x1+(x2-x1)/num*i,y1+(y2-y1)/num*i); } context.stroke(); } }; window.ChartDraws = ChartDraws; }(window,document));下面還有一個是實作requestAnimationFrame瀏覽器相容的
(function(){ var lastTime = 0; var prefixes = ['ms','webkit','o','moz']; //各浏览器前缀 var requestAnimationFrame = window.requestAnimationFrame; var cancelAnimationFrame = window.cancelAnimationFrame; var prefix; //通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式 for( var i = 0; i < prefixes.length; i++ ) { if ( requestAnimationFrame && cancelAnimationFrame ) { break; } prefix = prefixes[i]; requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ]; cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] || window[ prefix + 'CancelRequestAnimationFrame' ]; } //如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout if ( !requestAnimationFrame || !cancelAnimationFrame ) { requestAnimationFrame = function( callback, element ) { var currTime = new Date().getTime(); //为了使setTimteout的尽可能的接近每秒60帧的效果 var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ); var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall ); lastTime = currTime + timeToCall; return id; }; cancelAnimationFrame = function( id ) { window.clearTimeout( id ); }; } window.requestAnimationFrame = requestAnimationFrame; window.cancelAnimationFrame = cancelAnimationFrame; }());附上3f1c4e4b6b16bbbd69b2ee476dc4f83a呼叫
ChartDraws({ "containerId" : "chart1", //canvas所在容器id "canvasWidth" : 1000, "canvasHeight" : 250, "paddingLeft" : 50, "paddingTop" : 50, "columnChartData": [ {NO:0,PT:0.2,Name:"Html/Css"}, {NO:1,PT:0.4,Name:"Html5/Css3"}, {NO:2,PT:0.4,Name:"JavaScript"}, {NO:3,PT:0.5,Name:"JQuery"}, {NO:4,PT:0.2,Name:"Angular.js"}, {NO:5,PT:0.8,Name:"BootStrap"}, {NO:6,PT:0.6,Name:"React.js"}, {NO:7,PT:0.5,Name:"Java"} ], "yChartData" : [ {NO:0,Name:"熟悉"}, {NO:1,Name:"掌握"}, {NO:2,Name:"精通"} ], "isNeedAnimation" : false, "isNeedBorder" : false, "isNeedLineChart":true, "axisColor" : "#8DEEEE" }); ChartDraws({ "containerId" : "chart2", //canvas所在容器id "canvasWidth" : 1000, "canvasHeight" : 250, "paddingLeft" : 50, "paddingTop" : 50, "columnChartData": [ {NO:0,PT:0.4,Name:"Html/Css"}, {NO:1,PT:0.5,Name:"Html5/Css3"}, {NO:2,PT:0.2,Name:"JavaScript"}, {NO:3,PT:0.7,Name:"JQuery"}, {NO:4,PT:0.2,Name:"Angular.js"}, {NO:5,PT:0.3,Name:"BootStrap"}, {NO:6,PT:0.8,Name:"React.js"}, {NO:7,PT:0.2,Name:"Java"} ], "yChartData" : [ {NO:0,Name:"熟悉"}, {NO:1,Name:"掌握"}, {NO:2,Name:"精通"} ], "isNeedAnimation" : false, "isNeedBorder" : false, "isNeedLineChart":false, "isNeedColumnChart" : true, "columnChartColor":"#9370DB" }); ChartDraws({ "containerId" : "chart3", //canvas所在容器id "canvasWidth" : 1000, "canvasHeight" : 250, "paddingLeft" : 50, "paddingTop" : 50, "columnChartData": [ {NO:0,PT:0.4,Name:"Html/Css"}, {NO:1,PT:0.5,Name:"Html5/Css3"}, {NO:2,PT:0.2,Name:"JavaScript"}, {NO:3,PT:0.7,Name:"JQuery"}, {NO:4,PT:0.2,Name:"Angular.js"}, {NO:5,PT:0.3,Name:"BootStrap"}, {NO:6,PT:0.8,Name:"React.js"}, {NO:7,PT:0.2,Name:"Java"} ], "yChartData" : [ {NO:0,Name:"熟悉"}, {NO:1,Name:"掌握"}, {NO:2,Name:"精通"} ], "isNeedAnimation" : false, "isNeedBorder" : true, "isNeedLineChart":true, "isNeedColumnChart" : false, "lineChartColor" : "#8DB6CD", "borderColor" : "#87CEFA" })html代碼
<p class="section"> <p id="chart1"></p> <p id="chart2"></p> <p id="chart3"></p> </p>下面是一個實現後的效果圖 #在整個編碼的過程中我把程式碼改過一次,為什麼改呢,因為在第一次的時候我在js裡面使用了大量的ChartDraws.prototype.XXXX = function(){};後來我一想不對啊,我為什麼要把這麼多的方法暴露給外部呢. .....這不是沒事找事麼.......所以現在就改成這樣了,如果有不對的地方和可以改進的地方,希望路過的指點下,謝謝!還有那個白條程式碼背景怎麼刪不掉...........相關推薦:
以上是js封裝成插件_Canvas統計圖插件編寫實例_javascript技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!