之前就说过,我想写一个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;i2)
{
for(var i=1;i
下面还有一个是实现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;
}());
附上


