最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

js封装成插件_Canvas统计图插件编写实例

来源:懂视网 责编:小采 时间:2020-11-27 22:30:26
文档

js封装成插件_Canvas统计图插件编写实例

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

之前就说过,我想写一个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;
}());

附上<script>调用

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代码

<div class="section">
 <div id="chart1"></div>
 <div id="chart2"></div>
 <div id="chart3"></div>
 </div>

下面是一个实现后的效果图

在整个编码的过程中我把代码改过一次,为什么改呢,因为在第一次的时候我在js里面使用了大量的 ChartDraws.prototype.XXXX = function(){};

后来我一想不对啊,我为什么要把这么多的方法暴露给外部呢......这不是没事找事么.......

所以现在就改成这样了,如果有不对的地方和可以改进的地方,希望路过的指点下,谢谢!还有那个白条代码背景怎么删不掉...........

以上这篇js封装成插件_Canvas统计图插件编写实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

js封装成插件_Canvas统计图插件编写实例

js封装成插件_Canvas统计图插件编写实例:之前就说过,我想写一个canvas画统计图的插件,现在写好了 先说下实现的功能吧: 1.可以通过自定义X轴坐标属性和Y轴坐标属性按比例画出统计图 2.可以选择画折现图还是柱形统计图,或者两者都实现 3.可以自由定义折现颜色,坐标颜色,柱形图颜色 和can
推荐度:
标签: 插件 js 封装
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top