canvas实现折线图插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 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>

猜你喜欢

转载自blog.csdn.net/susuzhe123/article/details/80598547