canvas构建一个平面直角坐标系

功能:

  1:可设置只显示某个象限(onlyQuadrant)

     2:可设置刻度大小(setCalibration)

     3:可设置放大比例(setProportion)

可调用的方法(包括上面3个):

  向坐标系打印一点 (printPoint)

  在坐标画一条直线(printLine)

  设置下一画笔的填充色(setFillColor)

  设置下一画笔的边框色(setStrokeColor)

  获取某个坐标的真实x坐标(getx)

  获取某个坐标的真实y坐标(gety)

例子:http://jun-lu.github.com/jun/canvas_sin_cos_tan.html

源码:https://github.com/jun-lu/jun/blob/master/src/FlatSystem.js

/**
    平面直角坐标系类
    可以轻松在一块画布上画出平面直角坐标系,可设置宽度,高度,绘制比例,以及单位刻度
    构造函数 : FlatSystem
                context: 画布的2d上下文
                width:绘制的最大宽度
                height:绘制的最大高度
    属性设置:
            this.calibration=30 //刻度 可通过 setCalibration(number) 设置 ,这个方法也是对外API之一
            this.proportion=2 //绘制比例  可通过 setProportion(number) 设置这个方法也是对外API之一
    api:
        setCalibration(number);// 设置坐标系刻度
        setProportion();// 设置坐标系绘制比例
        init();//在画布上画出坐标系,如果在init之前没有设置刻度和绘制比例会使用默认的值
        clear(x,y,width,height)//清除画布的某块区域,如果不传递任何值会清空全部画布 
        
        
*/
function FlatSystem(context, width, height){
            
    this.context = context;
    this.width = width;
    this.height = height;
    this.calibration = 20;//刻度
    this.proportion = 2;//绘制比例
    this.jx = this.width/2; //0坐标点的x位置
    this.jy = this.height/2; //0坐标点的y位置
        
    //this.init();
    
}
FlatSystem.prototype = {
    constructor:FlatSystem,
    init:function(){
        this.context.clearRect(0,0,this.width, this.height);
        //this.width *= this.proportion;
        //this.height *= this.proportion;
        this.context.moveTo(0,0);
        this.setFillColor("#000");
        this.setStrokeColor("#000");
        this.build();
    },
    clear:function(x, y, width, height){
        this.context.clearRect(x ||0,y || 0,width || this.width, height || this.height);
    },
    setProportion:function(proportion){//整数
        this.proportion = proportion;
    },
    setCalibration:function(calibration){
        this.calibration = calibration;//刻度
    },    
    onlyQuadrant:function(quadran){//显示某一象限 1, 2, 3, 4
        if(quadran == 0){
            this.jx = this.width/2;
            this.jy = this.height/2;
        }
        
        if(quadran == 1){
            this.jx = 50;
            this.jy = this.height-50;
        }
        if(quadran == 2){
            this.jx = this.width - 50;
            this.jy = this.height - 50;
        }
        if(quadran == 3){
            this.jx = this.width -50;
            this.jy = 50;
        }
        if(quadran == 4){
            
            this.jx = 50;
            this.jy = 50;
        }
    },
    /**
        在坐标系统打印一个点
        x 轴坐标
        y 轴坐标
        width 点的宽度
        height 点的高度
    */
    printPoint:function(x,y,width,height){//默认点阵宽度2
    
        x = this.getx(x);
        y = this.gety(y);
        
        if(x < this.width &&  y < this.height){
            this.drawRect(x, y, width || 2, height || 2);
            return true;
        }
        return false;
    },
    /***
        在坐标系中画一条直线(线段)
        x 线段结束点 x坐标
        y 线段结束点 y坐标
        
        sx 线段开始点 x坐标 可选 不传递将会使用上次画笔结束点
        sy 线段开始点 y坐标 可选
        
    */
    printLine:function(x, y, sx, sy){
        this.drawLine(this.getx(x), this.gety(y), this.getx(sx),this.gety(sy));
    },
    /**
        设置填充色
    */
    setFillColor:function(color){
        this.context.fillStyle = color;
    },
    /**
        设置边框色
    */
    setStrokeColor:function(color){
        this.context.strokeStyle = color;
    },
    /**
        非公开
    */
    drawRect:function(x,y,width, height){

        this.context.beginPath();
        this.context.fillRect(x-width/2, y-height/2, width, height);
        this.context.stroke();
    },
    /***
        非公开
        在画布打印一个点,坐标为真实开始坐标和结束坐标
    */
    drawLine:function(x, y, sx, sy){//目标x y 开始sx sy
        this.context.beginPath();
        if(sx !== undefined && sy !== undefined ){
            this.context.moveTo(sx,sy);
        }
        //this.context.beginPath();
        this.context.lineTo(x, y);
        this.context.stroke();
    },
    fillText:function(text, x, y){
        this.context.fillText(text, this.getx(x), this.gety(y));
    },
    build:function(){//构建坐标系

        this.drawLine(this.jx, this.height, this.jx, 0);// y
        this.drawLine(0, this.jy, this.width,  this.jy);// x
        this.setFillColor('#d8d8d8');
        this.fillText("O", this.jx+5 , this.jy+10);//原点坐标 0
        this.buildCoordinate();// +x height/2
        
    },
    buildCoordinate:function(){//构建坐标系中的刻度和数字
        
        
        var calibration = this.calibration * this.proportion;//calibration 最小刻度
        var width = this.width;
        var height = this.height;
        
        // len = 中心点到4个最远点的最大绝对值 / 最小间隔单位
        var len = Math.max(
                    Math.max( Math.abs(this.getx(0) - width), Math.abs(this.getx(0) - 0) ), //x轴绝对最大值
                    Math.max( Math.abs(this.gety(0) - height ), Math.abs(this.gety(0) - 0) ) //y轴绝对最大值
                )*this.proportion / calibration;


        //this.setFillColor('#d8d8d8');
        var fixed = this.proportion >= 1 ? function(x){//对于绘制比例小于1 处理小位数
            return x;
        } : function(x){ return (x).toFixed(1);};
        
        
        
        var j=0;//中间变量
        var d = 0;
        var sx=0;
        var sy=0; 

        this.context.textBaseline = "middle";
        this.setFillColor('#d8d8d8');
        for(var i=1; i<=len;i++){//注释过的代码都是适当优化过的 其实等于没优化

            j = String(fixed(calibration*i));
            //console.log(typeof j);
            sx = this.getx(calibration*i);//第一象限
            sy = this.gety(0);
            
            this.drawLine(sx, sy, sx, sy-5);
            this.context.textAlign = "center";
            this.context.fillText(j, sx, sy+10);
            /***/
            
            sx = this.getx(-calibration*i);//第3象限
            //sy = this.gety(0);
            this.drawLine(sx, sy, sx, sy-5);
            this.context.fillText(j, sx, sy+10);
            /***/
            sx = this.getx(0);//第4象限
            sy = this.gety(-calibration*i);
            
            this.drawLine(sx, sy, sx-5, sy);
            this.context.textAlign = "left";
            this.context.fillText(j, sx+5, sy);
            /***/
            
            //sx = this.getx(0);//第2象限
            sy = this.gety(calibration*i);
            
            this.drawLine(sx, sy, sx-5, sy);
            this.context.fillText(j, sx+5, sy);
            /***/
        }


    },
    isIn:function(x, y){
        var x = this.getx(x);
        var y = this.gety(y);
        return x>=0 && x <= this.width && y>=0 && y<= this.height;
    },
    /**
        获取真实x坐标
    */
    getx:function(x){
        return parseInt(this.jx+(x/this.proportion));
    },
     /**
        获取真实x坐标
    */
    gety:function(y){
        return parseInt(this.jy-(y/this.proportion));
    }
};
原文地址:https://www.cnblogs.com/idche/p/2473943.html