仿echarts的折线图

10 篇文章 0 订阅
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>仿echarts的折线图</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        html,body{
            width:100%;
            height:100%;
        }
        #canvas{
            position:relative;
            margin:50px auto;
        }
    </style>
</head>
<body>
    <div id="canvas" style="width:500px;height:400px;"></div>
</body>
</html>
<script>
    var jquery = (function(){
        var $ = function(id){  //仿jquery $() 函数
            return document.getElementById(id) || id;
        }
        return $;
    }());


    var line = (function($){
        var extend = function(target,source){  //继承选项
            for(var key in source){
                if(key in target){
                    target[key] = source[key];
                }
            }
            return target;
        }
        var addEvent = function(obj,event,func){  //绑定事件
            obj.addEventListener ? obj.addEventListener(event,func) : obj.attachEvent("on"+event,function(){func.call(obj);});
        }
        window.requestAnimation = function(){  //window.requestanimation一秒60帧动画
            return  window.requestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    window.mozRequestAnimationFrame ||
                    window.msRequestAnimationFrame ||
                    window.oRequestAnimationFrame ||
                    function(fn){
                        window.setTimeout(fn,1000/60);
                    };
        }()
        var set = 0;
        var init = function(opt){
            this.option = {
                element : null,   //canvas的父元素id
                offsetleft : "6%",  //距离左侧的距离
                offsetright : "6%", //距离右侧的距离
                offsettop : "5%",   //距离顶部的距离
                offsetbottom : "95%", //x轴距离顶部的距离
                textoffsetx : 0,  //x轴文字的左右偏移量 ,正数往右,负数往左
                textoffsety : 20, //x轴文字的上下偏移量 ,整数往下 ,负数往上
                x : [],    //x轴的坐标数据
                data : [], //数据
                speed : 5  //动画移动的速度  1开始
            }
            this.coord = {
                x : [],  //储存x轴坐标
                xmin : 0,
                xmax : 0,
                xinterval : 0,
                y : [],  //储存y轴坐标
                ymin : 0,
                ymax : 0,
                yinterval : 0,
                data : []  //储存data坐标
            }
            extend(this.option,opt);
            this.option.offsetleft = this.option.offsetleft.substr(0,this.option.offsetleft.length-1)/100;
            this.option.offsetright = this.option.offsetright.substr(0,this.option.offsetright.length-1)/100;
            this.option.offsettop = this.option.offsettop.substr(0,this.option.offsettop.length-1)/100;
            this.option.offsetbottom = this.option.offsetbottom.substr(0,this.option.offsetbottom.length-1)/100;
            this.initialize();
        }


        init.prototype = {
            initialize : function(){
                this.canvas = this.createCanvas();
                this.canvas2 = this.createCanvas();
                this.canvas2.style = "position:absolute;z-index:1,top:0;left:0;";
                this.ctx = this.canvas.getContext("2d");
                this.ctx2 = this.canvas2.getContext("2d");
                this.drawCoordx();  //画x轴
                this.drawCoordy();  //画y轴
                this.drawData();  //画数据
                this.loopLine(this.coord.data[0].x,this.coord.data[0].y,this.coord.data[1].x,this.coord.data[1].y,1);  //画线条
            },
            loopLine : function(sx,sy,ex,ey,index){  //动画画线 ,参数:起始坐标x,起始坐标y,终点坐标x,终点坐标y, this.coord.data的下标
                var _this = this,xproportion = ex-sx,yproportion = ey-sy,yset = yproportion/xproportion;
                _this.option.speed = _this.option.speed > 1 ? _this.option.speed : 1;  //动画速度最小是1
                _this.ctx.save();
                _this.ctx.beginPath();
                _this.ctx.lineWidth=2;
                _this.ctx.strokeStyle="#aa0000";
                _this.ctx.moveTo(sx,sy);
                sx+= 1*_this.option.speed;
                sy+= (yset*_this.option.speed);
                if((sx >= ex && sy >= ey) || (sx >= ex && sy <= ey)){  //到达位置时
                    sx = ex;
                    sy = ey;
                    index++;
                    if(index !== _this.coord.data.length){ 
                        ex = _this.coord.data[index].x;
                        ey = _this.coord.data[index].y;
                    }
                }
                _this.ctx.lineTo(sx,sy);
                _this.ctx.stroke();
                _this.ctx.restore();
                if(index == _this.coord.data.length){ //循环到data的最大值就结束
                    return;
                }
                window.requestAnimation(function(){_this.loopLine(sx,sy,ex,ey,index);});
            },
            drawLine : function(){  //直接画线
                this.ctx.save();
                this.ctx.beginPath();
                this.ctx.lineWidth=2;
                this.ctx.strokeStyle="#aa0000";
                this.ctx.moveTo(this.coord.data[0].x,this.coord.data[0].y);
                for(var i = 1,len = this.coord.data.length;i < len;i++){  //循环数据直接使用lineTo画线
                    this.ctx.lineTo(this.coord.data[i].x,this.coord.data[i].y);
                }
                this.ctx.stroke();
                this.ctx.restore();


            },
            drawData : function(){  //画数据的坐标圆圈
                var coordyinterval = this.coord.y[0] !== "undefined" && this.coord.y[1] !== "undefined" ? this.coord.y[0].y - this.coord.y[1].y : 0,
                    proportion = coordyinterval/this.coord.yinterval; //获取的比例  


                for(var i = 0,len = this.option.data.length;i < len;i++){
                    var tmpcoord = {};
                    tmpcoord.x = Math.round(this.coord.xmin+(i*this.coord.xinterval),0);
                    tmpcoord.y = (this.canvas.height*this.option.offsetbottom-(this.option.data[i]*proportion));
                    this.coord.data.push(tmpcoord);


                    this.ctx2.save();
                    this.ctx2.beginPath();
                    this.ctx2.fillStyle = "#ffffff";
                    // this.ctx2.moveTo(tmpcoord.x,tmpcoord.y);
                    this.ctx2.arc(tmpcoord.x,tmpcoord.y,2,0,360*Math.PI/180);
                    this.ctx2.fill();
                    this.ctx2.restore();
                    
                    this.ctx2.save();
                    this.ctx2.beginPath();
                    this.ctx2.strokeStyle = "#aa0000";
                    // this.ctx2.moveTo(tmpcoord.x,tmpcoord.y);
                    this.ctx2.arc(tmpcoord.x,tmpcoord.y,2,0,360*Math.PI/180);
                    this.ctx2.stroke();
                    this.ctx2.restore();
                }
            },
            drawCoordy : function(){ //画y轴
                var lineheight = this.canvas.height-(this.canvas.height*this.option.offsettop+this.canvas.height*(1-this.option.offsetbottom)),  //y轴的长度
                    linewidth = this.canvas.width-(this.canvas.width*this.option.offsetleft+this.canvas.width*this.option.offsetright),  //x轴的长度
                    datamin = 0,  //数据最小值
                    datamax = 0,  //数据最大值
                    lineeachheight = lineheight/(this.option.data.length-1);  //单个y轴的长度
                for(var i = 0,len = this.option.data.length,datanum;i < len;i++){
                    datanum = 1;
                    for(var w = 1,lengs = this.option.data[i].toString().length;w < lengs;w++){
                        datanum = datanum+"0";
                    }
                    datamin = this.option.data[i] < datamin ? Math.floor(this.option.data[i]/datanum)*datanum : datamin;
                    datamax = this.option.data[i] > datamax ? Math.ceil(this.option.data[i]/datanum)*datanum : datamax;
                }
                this.coord.ymin = datamin;
                this.coord.ymax = datamax;
                this.coord.yinterval = Math.round(datamax/(this.option.data.length-1),0);
                this.ctx.save();
                this.ctx.beginPath();
                this.ctx.lineWidth = 1;
                this.ctx.strokeStyle = "#000";
                this.ctx.translate(0.5,0.5);  //linewidth = 1画出来的线,看起来和2一样,要使用translate(0.5,0.5) 就可以解决了
                this.ctx.moveTo(this.canvas.width*this.option.offsetleft,this.canvas.height*this.option.offsetbottom);
                this.ctx.lineTo(this.canvas.width*this.option.offsetleft,this.canvas.height*this.option.offsetbottom-lineheight);
                this.ctx.stroke();
                this.ctx.restore();
                for(var i = 0,len = this.option.data.length,offx,offy;i < len;i++){
                    var tmpcoord = {};
                    offx = this.canvas.width*this.option.offsetleft;
                    offy = this.canvas.height*this.option.offsetbottom-(i*lineeachheight);
                    if(i == 0){
                        tmpcoord.x = offx-this.ctx.measureText(this.coord.ymin).width-8;
                        tmpcoord.y = offy+5;
                    }else{
                        tmpcoord.x = offx-this.ctx.measureText(this.coord.ymin+(i*this.coord.yinterval)).width-8;
                        tmpcoord.y = offy+5;
                    }
                    this.coord.y.push(tmpcoord);
                    //画y轴刻度
                    this.ctx.save();
                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1;
                    this.ctx.strokeStyle = "#000";
                    this.ctx.translate(0.5,0.5);  //linewidth = 1画出来的线,看起来和2一样,要使用translate(0.5,0.5) 就可以解决了
                    this.ctx.moveTo(offx,offy);
                    this.ctx.lineTo(offx-5,offy);
                    this.ctx.stroke();
                    this.ctx.restore();
                    if(i > 0){  //起点不画y轴刻线
                        //画y轴刻线
                        this.ctx.save();
                        this.ctx.beginPath();
                        this.ctx.lineWidth = 1;
                        this.ctx.strokeStyle = "#ccc";
                        this.ctx.translate(0.5,0.5);  //linewidth = 1画出来的线,看起来和2一样,要使用translate(0.5,0.5) 就可以解决了
                        this.ctx.moveTo(offx,offy);
                        this.ctx.lineTo(offx+linewidth,offy);
                        this.ctx.stroke();
                        this.ctx.restore();
                    }
                    //画y轴标点
                    this.ctx.save();
                    this.ctx.fillStyle = "#000";
                    this.ctx.fillText(this.coord.ymin+(i*this.coord.yinterval),
                        tmpcoord.x,
                        tmpcoord.y);
                    this.ctx.restore();
                    
                }
            },
            drawCoordx : function(){  //画x轴
                var linewidth = this.canvas.width-(this.canvas.width*this.option.offsetleft+this.canvas.width*this.option.offsetright),  //x轴的长度
                    lineeachwidth = linewidth/(this.option.x.length-1);  //单个x轴的长度
                this.coord.xmin = this.canvas.width*this.option.offsetleft;
                this.coord.xmax = this.canvas.width*this.option.offsetleft+linewidth;
                this.coord.xinterval = lineeachwidth;


                this.ctx.save();
                this.ctx.beginPath();
                this.ctx.lineWidth = 1;
                this.ctx.strokeStyle = "#000";
                this.ctx.translate(0.5,0.5);  //linewidth = 1画出来的线,看起来和2一样,要使用translate(0.5,0.5) 就可以解决了
                this.ctx.moveTo(this.canvas.width*this.option.offsetleft,this.canvas.height*this.option.offsetbottom);
                this.ctx.lineTo(this.canvas.width*this.option.offsetleft+linewidth,this.canvas.height*this.option.offsetbottom);
                this.ctx.stroke();
                this.ctx.restore();
                for(var i = 0,len = this.option.x.length,offx,offy;i < len;i++){
                    var tmpcoord = {};
                    offx = this.canvas.width*this.option.offsetleft+(i*lineeachwidth);
                    offy = this.canvas.height*this.option.offsetbottom;
                    tmpcoord.x = offx-(this.ctx.measureText(this.option.x[i]).width/2)+this.option.textoffsetx;  //x坐标
                    tmpcoord.y = offy+this.option.textoffsety; //y坐标
                    this.coord.x.push(tmpcoord);
                    //画x轴刻度
                    this.ctx.save();
                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1;
                    this.ctx.strokeStyle = "#000";
                    this.ctx.translate(0.5,0.5);  //linewidth = 1画出来的线,看起来和2一样,要使用translate(0.5,0.5) 就可以解决了
                    this.ctx.moveTo(offx,offy);
                    this.ctx.lineTo(offx,offy+5);
                    this.ctx.stroke();
                    this.ctx.restore();
                    //画x轴标点
                    this.ctx.save();
                    this.ctx.fillStyle = "#000";
                    this.ctx.fillText(this.option.x[i],
                        tmpcoord.x,
                        tmpcoord.y);
                    this.ctx.restore();
                    
                }
            },
            createCanvas : function(){//创建canvas
                var canvas = document.createElement("CANVAS");
                canvas.innerHTML = "您的浏览器不支持canvas,赶紧换一个吧";
                $(this.option.element).appendChild(canvas);
                canvas.width = parseInt($(this.option.element).style.width);  //canvas的宽度要使用width
                canvas.height = parseInt($(this.option.element).style.height);//canvas的高度要使用height
                return canvas;
            }
        }
        return init;  //暴露参数给调用
    }(jquery || {})) //调用jquery module


    window.onload = function(){
        var option = {  //功能没echart强大,凑合着用
            element : "canvas",
            x : ["2017-11-01","2017-11-02","2017-11-03","2017-11-04","2017-11-05","2017-11-06","2017-11-07"],
            // x : ["狗","猫","山羊","猫头鹰","猪","老鼠","牛"],
            data : [10,0,35,20,67,4,89],
            offsetleft : "6%",  //距离左侧的距离,使用百分比
            offsetright : "6%", //距离右侧的距离,使用百分比
            offsettop : "5%",   //距离顶部的距离,使用百分比
            offsetbottom : "90%", //x轴距离顶部的距离,使用百分比
            textoffsetx : 1,  //x轴文字的左右偏移量 ,正数往右,负数往左
            textoffsety : 20, //x轴文字的上下偏移量 ,整数往下 ,负数往上
            speed : 5  //动画移动的速度  1开始
        }
        new line(option);  //初始化module
    }
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值