版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/susuzhe123/article/details/80598547
适用于手机端的折线图插件,通过canvas实现。
思路就是得到数据值,时间值,先画出x,y坐标轴,然后均分x轴,将时间点绘制上去,然后根据数据值,再求出x,y坐标点,使用lineTo绘制出连续折线图。注释在代码中。
/**
* @desc 绘制折线图
* @param {Object} defaultParam 配置参数
* @param {Object} id canvasid
* @param {Array } data 折线数据点
* @param {Array } time 时间点
* @param {Object} styleSet 样式设置 可省略
* @eg:
* var canvas2 = Charts({
* id:'can2', //id
* data:[20,60,60,80,100,120,140,60,100],
* time:["5-24","5-26","5-26","5-26","5-26","5-26","5-26","5-26","5-26"], //
* styleSet:{
* borderColor:'#a29fff',
* lineColor:'#8a93fe',
* pointColor:'#747efe'
* }
* })
*/
;(function(window,undefined){
function Charts(defaultParam){
//获取canvas父容器的宽度
var manyIndoorWd = document.getElementsByClassName('manyIndoor')[0].clientWidth,
can1 = document.getElementById(defaultParam.id);
//手机端自适应 设置canvas绘制元素宽度(默认300)
can1.width = manyIndoorWd,
//获取canvas绘制元素高度
height = can1.height - 20,
ctx = can1.getContext("2d"),
//初始数据
nums = defaultParam.data,
datas = defaultParam.time,
//默认颜色
setDefault = {
styleSet:{
borderColor:'#ff984e',
lineColor:'#ff984e',
pointColor:'#ff7854'
}
}
return new Charts.prototype.init(defaultParam,ctx,nums,datas,can1.width,height);
}
Charts.prototype = {
init: function(defaultParam,ctx,nums,datas,wd,ht){
//去除边界宽度
var wid = wd-24;
//获取数据的最大值并设置峰值0.88比例
var maxPoint = this.maxData(nums) / 0.88;
//参数合并
defaultParam = this.extend(setDefault,defaultParam);
//执行绘制函数
this.drawBorder(defaultParam,ctx,wd,ht)
this.drawLine(defaultParam,ctx,nums,wd,ht,wid,maxPoint)
this.drawPoint(defaultParam,ctx,nums,datas,wd,ht,wid,maxPoint)
return this;
},
drawBorder: function(defaultParam,ctx,wd,ht){
ctx.beginPath();
//手机端1px线条问题修复
ctx.translate(0.5, 0.5);
//10为默认边界宽度
ctx.moveTo(10,10);
ctx.lineTo(10,ht - 1);
ctx.moveTo(10,ht -1);
ctx.lineTo(wd - 10,ht -1);
ctx.closePath();
ctx.strokeStyle = defaultParam.styleSet.borderColor;
ctx.stroke();
},
drawLine: function(defaultParam,ctx,nums,wd,ht,wid,maxPoint){
for (i = 0;i < nums.length-1;i ++){
//起始坐标
var axiosY = ht - ht*nums[i]/maxPoint,
averNum= (wid/nums.length-1),
axiosX = i * averNum + 30,
//终止坐标
axiosNY = ht - ht*nums[i+1]/maxPoint,
axiosNX = (i+1) * averNum + 30;
//划线
ctx.beginPath();
ctx.moveTo(axiosX,axiosY);
ctx.lineTo(axiosNX,axiosNY);
ctx.lineWidth = 2;
ctx.strokeStyle = defaultParam.styleSet.lineColor;
ctx.setLineDash([0]);
ctx.closePath();
ctx.stroke();
//x轴上纵线
ctx.beginPath();
if(i == 0){
ctx.moveTo(axiosX,ht - 2);
ctx.lineTo(axiosX,axiosY);
}
ctx.moveTo(axiosNX,ht - 2);
ctx.lineTo(axiosNX,axiosNY);
ctx.lineWidth = 1;
ctx.setLineDash([2,8]);
ctx.strokeStyle = "#d6d6d6";
ctx.closePath();
ctx.stroke();
}
},
drawPoint:function(defaultParam,ctx,nums,datas,wd,ht,wid,maxPoint){
var len = nums.length;
//初始定义线条
ctx.lineWidth = 2;
ctx.strokeStyle = '#fff';
for (i = 0;i <= len;i ++){
var numsY = ht - ht*nums[i]/maxPoint,
numsX = i * (wid/nums.length-1) + 30;
//绘制圆点
ctx.beginPath();
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowBlur = 4;
ctx.shadowColor = defaultParam.styleSet.pointColor;
ctx.fillStyle = defaultParam.styleSet.pointColor;
ctx.setLineDash([0]);
ctx.arc(numsX , numsY, 5, 0, 2*Math.PI, false);
ctx.stroke();
ctx.fill();
ctx.closePath();
//折线上的点值
ctx.shadowBlur = 0;
ctx.fillStyle = '#222';
ctx.textAlign = 'center';
ctx.fillText(nums[i],numsX,numsY-10);
//绘制横坐标
if (i < nums.length){
var rowText = ctx.measureText(datas[i]);
ctx.textAlign = 'left';
ctx.fillText(datas[i],numsX-rowText.width/2,ht + 16);
}else if(i == nums.length) {
return;
}
ctx.closePath();
ctx.stroke();
}
},
maxData:function(arr){
return Math.max.apply(null,arr)
},
extend: function(defaults,newObj){
for (var i in newObj) {
defaults[i] = newObj[i];
}
return defaults;
}
}
Charts.prototype.init.prototype = Charts.prototype;
if(!window.Charts){
window.Charts = Charts;
}
})(window,undefined);
var canvas1 = Charts({
id:'can1',
data:[10,30,60,80,90,120,140,60,100],
time:["5-26","5-26","5-26","5-26","5-26","5-26","5-26","5-26","5-26"]
});
var canvas2 = Charts({
id:'can2',
data:[20,60,60,80,100,120,140,60,100],
time:["5-24","5-26","5-26","5-26","5-26","5-26","5-26","5-26","5-26"],
styleSet:{
borderColor:'#a29fff',
lineColor:'#8a93fe',
pointColor:'#747efe'
}
});
<div class=" boxList manyIndoor">
<canvas id="can2" height="180"></canvas>
</div>