canvas 基础用法

canvas是html5中诞生的一款HTML标签,用于绘制图像。元素本身没有绘制的能力,必须使用脚本来完成实际的绘图任务。
绘制canvas的主要步骤
  1. 获取canvas标签
  2. 获取绘制上下文
  3. 绘制图形

首先来一个简单的demo

  • 绘制矩形

html如下:

<canvas id="c1" style="width:500px;height:500px;"></canvas>

js如下:

    //canvas标签具有默认宽高:300*150
    //水平方向300像素,垂直方向150像素
    //设置canvas宽高:
    //1、通过样式:并没有增加canvas标签中的像素点的个数,只是改变了像素点的大小
    var canvas=document.querySelector("#c1"); //1、获取canvas标签
    var ctx=canvas.getContext("2d");  //2、获取绘制上下文
    ctx.fillRect(0,0,300,150); //3、绘制你想要的图像,(x,y,w,h)

就这样一个矩形就绘制好了

  • 绘制直线

html如下:

<canvas width="800" height="600"></canvas>

js如下:

  //1、获取canvas标签
    var canvas=document.querySelector("canvas");
    //2、获取绘图上下文(工具箱)
    var ctx=canvas.getContext("2d");//CanvasRenderContext2d
    //3、指定绘制的起点
    ctx.moveTo(50,50);//x轴坐标、y轴坐标
    //4、指定直线的终点
    ctx.lineTo(500,50); //x轴坐标、y轴坐标
        //lineCap设置线帽
    //ctx.lineCap="round";//圆形的线帽,相当于给线段左右两边分别加了2个半圆

    ctx.lineCap="square";
    //5、描边
    ctx.stroke();

就这样一个直线就绘制好了

  • 绘制正三角形
//将角度转换为弧度
    function toRadian(angle){
        return Math.PI*angle/180;
    }
    var length=100;
    var canvas=document.querySelector("canvas");
    var ctx=canvas.getContext("2d");
    //绘制正三角形
    function triangle(length,topX,topY){
        //三角形的高:h=sin 60°*边长
        var h=Math.sin(toRadian(60))*length;
        var leftX=topX-length/2;
        var leftY=topY+h;
        var rightX=topX+length/2;
        var rightY=topY+h;
        ctx.beginPath();
        ctx.moveTo(topX,topY);
        ctx.lineTo(leftX,leftY);
        ctx.lineTo(rightX,rightY);
        ctx.lineTo(topX,topY);  //等同于ctx.closePath();//将绘制的终点和绘制的起点连接起来
        ctx.fill();//填充图形
		 ctx.strokeStyle='pink'; //给绘制的图形描边
        ctx.stroke();
    }
    triangle(length,200,100);
    triangle(length,200,300);
  • ctx.beginPath()说明
** var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    //默认情况下,所有的绘图都是基于同一个状态的,
    //如果在某一段代码中多次调用了stroke方法,会将当前状态下的已经产生的轨迹都绘制一遍

    //举例:先绘制轨迹a,stroke;再绘制轨迹b,stroke;再绘制轨迹c,stroke;
    //-->a被绘制了3次,b被绘制了2次,c被绘制了1次

    //解决方案:通过beginPath()开启一个新的状态,在新状态中,所有的轨迹清空的
    ctx.moveTo(50,50);
    ctx.lineTo(300,50);
    ctx.strokeStyle="red";
    ctx.stroke();//红色的直线

    ctx.beginPath();
    ctx.moveTo(50,80);
    ctx.lineTo(300,80);
    ctx.strokeStyle="red";
    ctx.stroke();//红色的直线

    ctx.beginPath();
    ctx.moveTo(50,200);
    ctx.lineTo(300,200);
     ctx.lineWidth=2; //设置线宽
    ctx.strokeStyle="blue";
    ctx.stroke();//蓝色的直线


    //一般来说,在绘制新图形的时候,更多的会习惯性的开启新状态
    //每次开启新状态的时候,如果没有指定新的状态值(比如:描边色),将会继承上一状态下的该值**
  • 绘制虚线
    1.第一种方法
   var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    var smallLength=10;
    var spaceLength=5;

    var x=50,y=50;
    //0、  50,50-->50+10,50
    //1、  50+10+5,50-->50+10+5+10,50
    //2、  50+10+5+10+5,50-->50+10+5+10+5+10
    //i,  50+(10+5)i        50+(10+5)i+10
    for (var i = 0; i < 10; i++) {
        ctx.moveTo(x+(smallLength+spaceLength)*i,50);
        ctx.lineTo(x+(smallLength+spaceLength)*i+smallLength,50);
    }
    ctx.stroke();

2.第二种方法

  var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    ctx.moveTo(50,50);
    ctx.lineTo(500,50);
    //[]    数组中没有任何元素,绘制出来的还是实线
    //[i]   只有一个元素表示实线部分和空白部分的长度相等,均为i
    //[i,j]  有2个元素,表示i为实线部分的长度,j为空白部分的长度
    //[i,j,g] 有3个元素,第一个实线部分长度为i,第一个空白部分长度为j,第二个实线部分长度为g,第二个空白部分长度为i
    //[i,j,g,s] 有4个元素,第一个实线部分长度为i,第一个空白为j,第二个实线为g,第二个空白为s
    ctx.setLineDash([10,5,2,5]);
    ctx.lineWidth=2;
    ctx.stroke();

3.绘制虚线矩形

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    //完成绘制指定的矩形
    function rect(x,y,width,height){
        ctx.moveTo(x,y);
        ctx.lineTo(x+width,y);
        ctx.lineTo(x+width,y+height);
        ctx.lineTo(x,y+height);
        ctx.closePath();
        ctx.setLineDash([10,5,2,5,5,5,3,5,8,5,6,5,2,5]);
        //获取上面设置的虚线的属性值
	    //如果设置的时候数组长度为奇数,打印出来的将是:数组*2
	    //...................为偶数,打印出来的将是它本身
    	console.log(ctx.getLineDash());
    	 //lineDashOffset:
	    //1、值为负数:线条向右出来指定的像素
	    //2、值为正数,线条向左缩进去指定的像素
	    ctx.lineDashOffset=-8;
        ctx.lineWidth=2;
        ctx.strokeStyle="red";
        ctx.stroke();
    }
    rect(50,50,300,200);
  • 绘制跑马灯
var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");


    function rect(x,y,width,height){
        ctx.moveTo(x,y);
        ctx.lineTo(x+width,y);
        ctx.lineTo(x+width,y+height);
        ctx.lineTo(x,y+height);
        ctx.closePath();

        ctx.setLineDash([10,5,2,5]);

        ctx.lineDashOffset--;

        ctx.lineWidth=2;
        ctx.strokeStyle="red";
        ctx.stroke();
    }
    var timer=setInterval(function(){
        ctx.beginPath();
        ctx.clearRect(0,0,canvas.width,canvas.height); //清空画布,
        rect(50,50,300,200);
        ctx.stroke();//如果没有beginPath,就算是清空了画布,但是路径依然存在
        //随着动画的运行,无数次调用了stroke方法,都会对之前的路径进行重绘
    },10);
  • 绘制相交线
 var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    ctx.moveTo(50,50);
    ctx.lineTo(300,300);
    ctx.lineTo(500,50);

    ctx.lineWidth=50;

    ctx.lineJoin="round";
//    ctx.lineJoin="bevel";

    ctx.stroke();
  • 绘制折现图
  var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    var yTopX = 50, yTopY = 50,
            yLength = 500, xLength = 500,
            b = 30, h = 30;
    var zeroX=yTopX,zeroY=yTopY+yLength;
    var xTopX=yTopX+xLength,xTopY=yTopY+yLength;

    //1、绘制y轴小三角形
    ctx.moveTo(yTopX-b/2,yTopY+h);//p1
    ctx.lineTo(yTopX,yTopY);
    ctx.lineTo(yTopX+b/2,yTopY+h);//p2

    //2、绘制y轴、x轴折线
    ctx.moveTo(yTopX,yTopY);
    ctx.lineTo(zeroX,zeroY);
    ctx.lineTo(yTopX+xLength,yTopY+yLength);

    //3、绘制x轴小三角形(r1-r2-r3)
    ctx.moveTo(yTopX+xLength-h,yTopY+yLength-b/2);
    ctx.lineTo(yTopX+xLength,yTopY+yLength);
    ctx.lineTo(yTopX+xLength-h,yTopY+yLength+b/2);

    ctx.stroke();

    var data=[{x:50,y:250},{x:160,y:170},{x:200,y:200},{x:280,y:155},{x:350,y:300}];

    //data2保存了每一个数据位于画布中的坐标
    var data2=data.map(function(obj){
        var objNew={};
        objNew.x=zeroX+obj.x;
        objNew.y=zeroY-obj.y;

        return objNew;
    });
    console.log(data2);

    //绘制每一个点
    data2.forEach(function(obj){
        //以obj为中心,绘制边长为4的实心小正方形

        var x=obj.x,y=obj.y;

        ctx.beginPath();
        ctx.moveTo(x-2,y-2);
        ctx.lineTo(x+2,y-2);
        ctx.lineTo(x+2,y+2);
        ctx.lineTo(x-2,y+2);
        ctx.fill();
    });

    //连线
    ctx.beginPath();
    data2.forEach(function(obj,index){
        if(index==0){
            ctx.moveTo(zeroX,zeroY);
        }
        ctx.lineTo(obj.x,obj.y);
    });
    ctx.stroke();

    //绘制文字:
    ctx.font="30px Microsoft Yahei";

    ctx.textAlign="right";
    ctx.fillText("y",yTopX,yTopY);

    ctx.textBaseline="hanging";
    ctx.fillText("0",zeroX,zeroY);

    ctx.fillText("x",xTopX,xTopY);

    //绘制点的坐标:
    ctx.font="16px Microsoft Yahei";
    ctx.textAlign="center";
    ctx.textBaseline="bottom";

    data.forEach(function(obj){
        ctx.fillText("("+obj.x+","+obj.y+")",zeroX+obj.x,zeroY-obj.y);
    });
  • 绘制文本
 var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    ctx.font="30px 微软雅黑";  //设置字体
    ctx.strokeStyle="hotpink"; //设置字体颜色
    ctx.strokeText("Hello ni",50,50);   //设置字体内容和坐标,空心字体

    ctx.fillStyle="red";
     //textAlign:文本的水平对齐方式(默认值是 start)
    //1. left 文本左对齐(文字的最左边靠着起点x轴所在)
    //2. right 文本右对齐
    //3. center 文本居中对齐
    //4. start相当于left
    //5. end:相当于right
     ctx.textAlign="end";  //是在字体坐标的位置的对其方式
     //textBaseLine:文本的垂直对齐方式(默认值是 alphabetic)
    //1. top:文本基线在文本块的顶部。
    //2. hanging:文本基线是悬挂基线。
    //3. middle:文本基线在文本块的中间。(文字垂直居中)
    //4. alphabetic:文本基线是标准的字母基线(英语四线格的第三条线)
    //5. bottom:文本基线在文本块的底部。
     ctx.textBaseline="middle"; 
      // measureText("文本内容")
     // 返回一个对象,该对象中含有width属性表示文本的宽度
     //在计算文本宽度的时候,会自动判定当前状态下设置的字体大小
    var obj=ctx.measureText("Hello Javascript22222222222!");
    console.log(obj.width);//获取文本的宽度
    ctx.fillText("hellow",50,200); //实心字体
  • 绘制弧形
    1.绘制圆弧
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    ctx.arc(300,300,150,0.7*Math.PI,1.3*Math.PI);//(x,y,r,start,end)
    ctx.stroke();

2.绘制扇形

   var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    ctx.moveTo(300,300);
    ctx.arc(300,300,150,0,-0.5*Math.PI,true);
    ctx.closePath();
    ctx.stroke();
  • 绘制饼图
var colors = (function () {
        return (
        "darkslategrey,darkturquoise,darkviolet,deeppink,deepskyblue,dimgray,dimgrey,dodgerblue,firebrick," +
        "floralwhite,forestgreen,fuchsia,gainsboro,ghostwhite,gold,goldenrod,gray,green,greenyellow,grey," +
        "honeydew,hotpink,indianred,indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon," +
        "lightblue,lightcoral,lightcyan,lightgoldenrodyellow" ).split(',');
    })();

    /**
     *
     * @param ctx 指定绘图上下文,从而确定在哪个canvas中绘制饼图
     * @param x
     * @param y
     * @param r
     * @param data
     * @constructor
     */
    function Bing(obj) {
        //第一个扇形的起始弧度
        this.start = 0;

        var self=this;

        //以下功能就是为了实现将Obj中的属性拷贝到this中-->混入继承($.each)
        $.each(obj,function(key,v){
            //要将v赋值给bing的实例
            self[key]=v;
        })

        this.init();
    }

    Bing.prototype = {
        constructor: Bing,
        init: function () {
            //1、处理数据
            this.processData();

            //2、绘制扇形
            this.drawShanxings();

            //3、绘制文字
            this.drawText();

        },
        processData: function () {
            //1、计算数据的总和
            var sum = 0;
            this.data.forEach(function (v) {
                sum += v;
            });
            //2、计算每一个数据所占的比重
            this.data2 = this.data.map(function (v) {
                var obj = {};
                obj.number = v;
                obj.ratio = v / sum;//每个数据占据的比重
                obj.radian = 2 * Math.PI * v / sum;//该扇形所占据的弧度
                obj.start = this.start;
                obj.end = this.start + obj.radian;

                this.start = obj.end;

                return obj;
            }, this);
        },

        drawShanxings: function () {
            //3、计算每一个扇形的起始弧度和结束弧度
            this.data2.forEach(function (obj, i) {

                //绘制扇形:
                this.drawShanxing(300, 300, 150, obj.start, obj.end, colors[i]);

            }, this);
        },

        drawShanxing: function (x, y, r, start, end, color) {
            var ctx = this.ctx;

            ctx.beginPath();
            ctx.moveTo(x, y);
            ctx.arc(x, y, r, start, end);
            ctx.fillStyle = color;
            ctx.fill();
        },

        drawText:function(){
            this.ctx.font="30px 微软雅黑";

            //遍历this.data2
            this.data2.forEach(function(obj){
                //var obj = {number:"用户的数据",ratio:"",radian:"",start:"",end:""};

                //计算文字位于的弧度
                var r2=obj.start+obj.radian/2;

                var h=Math.sin(r2)*this.r;
                var b=Math.cos(r2)*this.r;

                //计算文字的坐标
                var x2=this.x+b;
                var y2=this.y+h;

                this.ctx.fillText(obj.number,x2,y2);

            },this)
        }
    };
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var data = [1, 3, 5, 7, 9];

    var bing = new Bing({
        ctx: ctx,
        x: 300,
        y: 300,
        r: 150,
        data: data
    });
  • 设置链子
var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    var colors = (function () {
        return ( "aliceblue,antiquewhite,aqua,aquamarine,azure,beige,bisque,black,blanchedalmond,blue," +
        "blueviolet,brown,burlywood,cadetblue,chartreuse,chocolate,coral,cornflowerblue,cornsilk," +
        "crimson,cyan,darkblue,darkcyan,darkgoldenrod,darkgray,darkgreen,darkgrey,darkkhaki,darkmagenta," +
        "darkolivegreen,darkorange,darkorchid,darkred,darksalmon,darkseagreen,darkslateblue,darkslategray," +
        "darkslategrey,darkturquoise,darkviolet,deeppink,deepskyblue,dimgray,dimgrey,dodgerblue,firebrick," +
        "floralwhite,forestgreen,fuchsia,gainsboro,ghostwhite,gold,goldenrod,gray,green,greenyellow,grey," +
        "honeydew,hotpink,indianred,indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon," +
        "lightblue,lightcoral,lightcyan,lightgoldenrodyellow,lightgray,lightgreen,lightgrey,lightpink," +
        "lightsalmon,lightseagreen,lightskyblue,lightslategray,lightslategrey,lightsteelblue,lightyellow," +
        "lime,limegreen,linen,magenta,maroon,mediumaquamarine,mediumblue,mediumorchid,mediumpurple," +
        "mediumseagreen,mediumslateblue,mediumspringgreen,mediumturquoise,mediumvioletred,midnightblue," +
        "mintcream,mistyrose,moccasin,navajowhite,navy,oldlace,olive,olivedrab,orange,orangered,orchid," +
        "palegoldenrod,palegreen,paleturquoise,palevioletred,papayawhip,peachpuff,peru,pink,plum,powderblue," +
        "purple,rebeccapurple,red,rosybrown,royalblue,saddlebrown,salmon,sandybrown,seagreen,seashell,sienna," +
        "silver,skyblue,slateblue,slategray,slategrey,snow,springgreen,steelblue,tan,teal,thistle,transparent," +
        "tomato,turquoise,violet,wheat,white,whitesmoke,yellow,yellowgreen" ).split(',');
    })();

    function Chain(opt) {
        if (!opt) throw new Error("请设置相关参数");


        if (!opt.ctx) throw new Error("请传递上下文");
        if (!opt.bigX) throw new Error("请传递大圆圆心x");
        if (!opt.bigY) throw new Error("请传递大圆圆心y");

        var _defaultOpt = {
            num: 5,
            start: 0,
            bigRadius: 150,
            smallRadius: 10
        };

        $.extend(this, _defaultOpt, opt);

        this.init();
    }

    Chain.prototype = {
        constructor: Chain,
        init: function () {
            //1、绘制大圆
            this.drawBigCircle();

            //2、绘制小圆
            this.drawSmallCircles();

        },

        drawBigCircle: function () {
            var ctx = this.ctx;
            ctx.beginPath();
            ctx.arc(this.bigX, this.bigY, this.bigRadius, 0, 2 * Math.PI);
            ctx.stroke();
        },

        drawSmallCircles: function () {
            var radian = 2 * Math.PI / this.num;//相邻小圆的圆心之间的弧度差

            for (var i = 0; i < this.num; i++) {
                var smallRadian = this.start + radian * i;//该小圆的圆心位于大圆的弧度值

                this.drawSmallCircle(smallRadian,colors[i+15]);

            }
        },


        drawSmallCircle: function (smallRadian,color) {
            var b = this.bigRadius * Math.cos(smallRadian);
            var h = this.bigRadius * Math.sin(smallRadian);
            //计算小圆的圆心的坐标
            var sX = this.bigX + b;
            var sY = this.bigY + h;

            var ctx = this.ctx;

            ctx.save();

            ctx.beginPath();
            ctx.arc(sX, sY, this.smallRadius, 0, 2 * Math.PI);
            ctx.fillStyle=color;
            ctx.fill();

            ctx.restore();
        }

    };
    //j表示行索引,i表示列索引
    for (var j = 0; j < 5; j++) {
        for (var i = 0; i < 10; i++) {
            var chain=new Chain({
                ctx: ctx,
                bigX: 60+i*120,
                bigY: 60+j*120,
                bigRadius: 50,
                num: 3+10*j+i,
                smallRadius: 5,
                start: 0
            });
        }
    }

  • 旋转小球
var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    function Chain(opt) {
        if (!opt) throw new Error("请设置相关参数");


        if (!opt.ctx) throw new Error("请传递上下文");
        if (!opt.bigX) throw new Error("请传递大圆圆心x");
        if (!opt.bigY) throw new Error("请传递大圆圆心y");

        var _defaultOpt = {
            start: 0,
            bigRadius: 150,
            smallRadius: 10
        };

        $.extend(this, _defaultOpt, opt);

        this.num=this.data.length;

        this.init();
    }
    Chain.prototype = {
        constructor: Chain,
        init: function () {
            this.ctx.font="30px 微软雅黑";
            this.ctx.textAlign="center";
            this.ctx.textBaseline="middle";

            //让动画以较快的方式运行
            this.run(10);

            this.bindEvents();


        },

        run: function (speed) {
            var self = this;
            clearInterval(this.timer);
            this.timer = setInterval(function () {
                var ctx = self.ctx;

                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);


                //1、绘制大圆
                self.drawBigCircle();

                //2、绘制小圆
                self.drawSmallCircles();

                //3、进行动画的增量:start
                self.start += 0.01 * Math.PI;
            }, speed);
        },

        bindEvents: function () {
            var canvas = this.ctx.canvas;

            var self = this;

            $(canvas).on("mouseenter", function () {
                self.run(50);
            }).on("mouseleave", function () {
                self.run(10);
            });
        },

        drawBigCircle: function () {
            var ctx = this.ctx;
            ctx.beginPath();
            ctx.arc(this.bigX, this.bigY, this.bigRadius, 0, 2 * Math.PI);
            ctx.stroke();
        },

        drawSmallCircles: function () {
            this.ctx.fillStyle = "pink";

            var radian = 2 * Math.PI / this.num;//相邻小圆的圆心之间的弧度差

            for (var i = 0; i < this.num; i++) {
                var smallRadian = this.start + radian * i;//该小圆的圆心位于大圆的弧度值

                this.drawSmallCircle(smallRadian,this.data[i]);

            }
        },


        drawSmallCircle: function (smallRadian,data) {
            var b = this.bigRadius * Math.cos(smallRadian);
            var h = this.bigRadius * Math.sin(smallRadian);
            //计算小圆的圆心的坐标
            var sX = this.bigX + b;
            var sY = this.bigY + h;

            var ctx = this.ctx;

            ctx.beginPath();
            ctx.arc(sX, sY, this.smallRadius, 0, 2 * Math.PI);
            ctx.fill();


            ctx.save();
            ctx.fillStyle="#daa520";
            ctx.fillText(data,sX,sY);
            ctx.restore();
        }
    };

    var opt = {
        ctx: ctx,
        bigX: 300,
        bigY: 300,
        bigRadius: 200,
        smallRadius: 60,
        start: 0,
        data: ["javascript", "php", "oc", "python", "ruby", "java"]
    }
    new Chain(opt);
  • 时钟
<script src="jquery-2.1.4.js"></script>
<script src="clock.js"></script>
<script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");


    //要绘制大圆:必须知道大圆的圆心和半径
    //要绘制刻度线,必须要知道刻度线的长度和线宽
    //要绘制文字:必须要知道:文字大小,字体,颜色
    var clock=new Clock({
        ctx:ctx,
        bigX:300,
        bigY:300,
        bigRadius:150,
        bigLength:20,
        smallLength:8,
        bigWidth:8,
        smallWidth:4,
        fontSize:"20px",
        fontFamily:"微软雅黑",
        fontColor:"red"
    })
</script>

clock.js

/**
 *
 * Created by ChengXiancheng on 2017/3/11.
 */


function Clock(opt){

    $.extend(this,opt);

    this.ctx.font=this.fontSize+" "+this.fontFamily;
    this.ctx.textAlign="center";
    this.ctx.textBaseline="middle";

    this.init();
}
Clock.prototype={
    constructor:Clock,
    init:function(){
        var self=this;
        var ctx=self.ctx;
        this.timer=setInterval(function(){
            ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);

            //绘制大圆
            self.drawBigCircle();
            //绘制刻度盘
            self.drawDial();
            //绘制指针
            self.drawPoints();
        },1000);



    },
    drawPoints:function(){
        //根据指定的时间绘制指针
        var date=new Date();

        var hour=date.getHours();//小时数:0-23之间
        var hour2=hour%12;//计算出0-11之间的值
        //发现0位于-PI/2
        //计算时针的弧度值
        //      a、计算相邻时针之间的弧度差
        //      b、弧度差*时间
        //      c、发现"0时"位于-PI/2的弧度,所以应该把上面的结果减去PI/2
        var hourRadian=2*Math.PI/12*hour2-Math.PI/2;
        //绘制指针
        this.drawPoint(20,hourRadian,"red",8);

        var minute=date.getMinutes();//分钟数:0-59
        var minuteRadian=2*Math.PI/60*minute-Math.PI/2;
        //绘制指针
        this.drawPoint(50,minuteRadian,"green",5);

        var second=date.getSeconds();//秒数:0-59
        var secondRadian=2*Math.PI/60*second-Math.PI/2;
        //绘制指针
        this.drawPoint(70,secondRadian,"blue",3);
    },

    drawBigCircle:function(){
        var ctx=this.ctx;

        ctx.save();
        ctx.strokeStyle="#335F9A";
        ctx.lineWidth=10;
        
        ctx.beginPath();
        ctx.arc(this.bigX,this.bigY,this.bigRadius,0,2*Math.PI);
        ctx.stroke();

        ctx.restore();
    },
    //绘制刻度盘
    drawDial:function(){

        var bigRadius=this.bigRadius-10/2;//减去大圆的线宽的一半

        var ctx=this.ctx;

        //第一个刻度线位于大圆的弧度值
        var start=-Math.PI/3;

        var radian=2*Math.PI/60;//相邻刻度线之间的弧度差

        for (var i = 0; i < 60; i++) {
            //计算出每一个刻度线的弧度值
            var smallRadian=start+radian*i;

            var length,lineWidth;//保存刻度线的线宽
            //有2种刻度,i被5整除是长刻度,其他都是短刻度
            if(i%5==0){
                length=this.bigLength;
                lineWidth=this.bigWidth;

                //指定文字与大圆圆心之间的距离
                this.drawText(i/5+1,smallRadian);

            }else{
                length=this.smallLength;
                lineWidth=this.smallWidth;
            }

            var h1=Math.sin(smallRadian)*(bigRadius-length);
            var b1=Math.cos(smallRadian)*(bigRadius-length);

            var h2=Math.sin(smallRadian)*bigRadius;
            var b2=Math.cos(smallRadian)*bigRadius;

            //刻度线起点坐标
            var x1=this.bigX+b1,y1=this.bigY+h1;
            //刻度线的终点坐标
            var x2=this.bigX+b2,y2=this.bigY+h2;

            ctx.save();
            ctx.lineWidth=lineWidth;

            ctx.beginPath();
            ctx.moveTo(x1,y1);
            ctx.lineTo(x2,y2);
            ctx.stroke();

            ctx.restore();

            //刻度线的起始坐标和结束坐标的推导公式:
            // sin smallR=h1/(bigR-length)
            // -->h1=sin smallR*(bigR-length)
            // -->b1=cos smallR*(bigR-length)
            //
            // sin smallR=h2/bigR
            // -->h2=sin smallR*bigR;
            // -->b2=cos smallR*bigR;
            //
            // x1=bigX+b1,y1=bigY+h1
            // x2=bigX+b2,y2=bigY+h2;

        }
    },

    drawText:function(text,smallRadian){
        //指定文字与大圆圆心之间的距离
        var r=110;
        var b3=Math.cos(smallRadian)*r;
        var h3=Math.sin(smallRadian)*r;
        //计算文字的坐标
        var x3=this.bigX+b3,y3=this.bigY+h3;

        this.ctx.fillText(text,x3,y3);
    },

    /**
     *
     * @param length 指针的长度
     * @param radian 指针的终点位于大圆的弧度值
     */
    drawPoint:function(length,radian,color,width){
        var b=Math.cos(radian)*length;
        var h=Math.sin(radian)*length;
        //计算出指针终点的坐标
        var x=this.bigX+b,y=this.bigY+h;
        //绘制指针:
        var ctx=this.ctx;
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(this.bigX,this.bigY);
        ctx.lineTo(x,y);
        ctx.strokeStyle=color;
        ctx.lineWidth=width;
        ctx.stroke();
        ctx.restore();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值