Javascript & HTML5 Canvas 时钟绘制

版权声明:无私奉献,希望大家转载注明出处,谢谢! https://blog.csdn.net/littlebrain4solving/article/details/78958611

说明

我这里采用 JavascriptHTML5 Canvas API 来进行 Graphic2D 的绘制,主要利用数学的三角函数与圆有关的公式来达到目的,其实最主要是通过实际练习并对这些数学公式进行深入掌握;也希望能够帮助大伙儿明白其中的原理,我尽量用比较详细的方式进行编写这篇博文。

效果图

IMAGE

数学知识

  1. 圆的弧度与角度的关系,以及圆的基础知识。
    圆周率(π) = 圆周长 / 圆直径(周长与直径的比值);在计算机领域的数学公式计算坐标都是根据弧度为单位进行计算,那我们在计算时就需要把角度转弧度;角度转弧度的根本原理 —— 圆周率就是180°角的弧度,那么角度转弧度公式可以为:角度 / 180° * π,而弧度转角度:弧度 / π * 180°。

  2. 什么是余弦值与正弦值、正切值。
    IMAGE
    按以上图为例,已知直角三角形AC、AB、BC的长度,想要获取“a”弧度值,咱们可以利用三种方式进行获取,余弦值 —— 对边/斜边(即AB/AC),正弦值 —— 临边/斜边(即BC/AC),正切值 —— 临边/对边(即BC/AB);在数学中如果知道相应的值后可以利用查表的方式得出弧度;计算机中可以利用反函数获取弧度。

相关注意事项: 在计算机中不管是余弦值、正弦值、正切值都有对应的反余弦值、反正弦值、反正切值函数,而函数返回的内容就是咱们需要的弧度/角度值;

计算机Math函数列表

● Math.sin —— 正弦值获取函数
● Math.cos —— 余弦值获取函数
● Math.tan —— 正切值获取函数
● Math.asin —— 反正弦值函数获取弧度
● Math.acos —— 反余弦值函数获取弧度
● Math.atan —— 反正切值函数获取弧度
● Math.atan2 —— 这个函数是计算机特有的升级版反正切函数,应用数学中不存在这种说法,只需要传入一条射线从A点到B点的对应位置即可获取到咱们想要的弧度;如上图:“a”的弧度 = Math.atan2(C坐标,A坐标)。

核心代码

以下相关的代码使用了 JQuery,如果需要运行起来则需要在HTML里面导入JQuery相关的库,然后再把以下语句拷贝至单独JS文件或HTML中。此份代码可以通过我的 Github 地址进行获取:https://github.com/caryyu/clock

画圆与旋转指针

Clock = function(){
    var jCanvas = $('<canvas width="450" height="300">');
    //jCanvas.on('mousemove',onMousemove);
    $(document.body).append(jCanvas);
    this.canvas = jCanvas[0];
    this.ctx = this.canvas.getContext('2d');
    this.ctx.strokeStyle = 'red';
    this.ctx.fillStyle = 'red';
    this.rect = {w:this.canvas.width,h:this.canvas.height,x:0,y:0};
    this.radius = 50;
    this.count = 0;
    this.interval = 100;
};

Clock.prototype = {
    drawing : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Core Drawing 
        this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.ctx.beginPath();
        this.ctx.arc(rx,ry,radius,0,2 * Math.PI);
        var radian = (Math.PI * 2 / 12) * this.count;
        var x = Math.cos(radian) * radius;
        var y = Math.sin(radian) * radius;
        this.ctx.moveTo(rx,ry);
        this.ctx.lineTo(rx + x , ry + y);
        this.ctx.stroke();
        //Counting for drawing
        this.count++;
        if(this.count > 12){this.count = 1}
    },
    start : function(){
        setInterval($.proxy(this.drawing,this),this.interval);
    }
};

function globalToLocal(canvas, x, y) {
  var bbox = canvas.getBoundingClientRect();
  var x = x - bbox.left * (canvas.width / bbox.width);
    var y = y - bbox.top  * (canvas.height / bbox.height);
    return {x: x, y : y};
}


$(function(){
    var c = new Clock();
    c.start();
});

时钟标记绘制

Clock = function(){
    var jCanvas = $('<canvas width="450" height="300">');
    //jCanvas.on('mousemove',onMousemove);
    $(document.body).append(jCanvas);
    this.canvas = jCanvas[0];
    this.ctx = this.canvas.getContext('2d');
    this.ctx.strokeStyle = 'red';
    this.ctx.fillStyle = 'red';
    this.rect = {w:this.canvas.width,h:this.canvas.height,x:0,y:0};
    this.radius = 50;
    this.count = 1;
    this.interval = 200;
};

Clock.prototype = {
    drawingMarks : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Hour Wheel Marks
        for(var i=1;i<=12;i++){
            var radian = (Math.PI * 2 / 12) * i;
            var p1 = this.getPoint(radian,radius - 8);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
        //Minute Wheel Marks
        for(var j=1;j<=60;j++){
            var radian = (Math.PI * 2 / 60) * j;
            var p1 = this.getPoint(radian,radius - 3);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
    },
    drawing : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Core Drawing 
        this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.ctx.beginPath();
        this.ctx.arc(rx,ry,radius,0,2 * Math.PI);
        var radian = (Math.PI * 2 / 12) * this.count;
        var p = this.getPoint(radian,radius);
        this.drawingMarks();
        this.ctx.moveTo(rx, ry);
      this.ctx.lineTo(rx + p.x , ry + p.y);
        this.ctx.stroke();
        //Counting for drawing
        this.count++;
        if(this.count > 12){this.count = 1}
    },
    getPoint : function(radian,radius){
        var x = Math.cos(radian) * radius;
        var y = Math.sin(radian) * radius;
        return {x : x , y : y};
    },
    start : function(){
        //this.drawing();
        setInterval($.proxy(this.drawing,this),this.interval);
    }
};

function globalToLocal(canvas, x, y) {
  var bbox = canvas.getBoundingClientRect();
  var x = x - bbox.left * (canvas.width / bbox.width);
    var y = y - bbox.top  * (canvas.height / bbox.height);
    return {x: x, y : y};
}


$(function(){
    var c = new Clock();
    c.start();
});

时钟时分秒针绘制

Clock = function(){
    var jCanvas = $('<canvas width="450" height="300">');
    //jCanvas.on('mousemove',onMousemove);
    $(document.body).append(jCanvas);
    this.canvas = jCanvas[0];
    this.ctx = this.canvas.getContext('2d');
    this.ctx.strokeStyle = 'red';
    this.ctx.fillStyle = 'red';
    this.rect = {w:this.canvas.width,h:this.canvas.height,x:0,y:0};
    this.radius = 50;
    this.count = 1;
    this.interval = 1000;
};

Clock.prototype = {
    drawingMarks : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Hour Wheel Marks
        for(var i=1;i<=12;i++){
            var radian = (Math.PI * 2 / 12) * i;
            var p1 = this.getPoint(radian,radius - 8);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
        //Minute Wheel Marks
        for(var j=1;j<=60;j++){
            var radian = (Math.PI * 2 / 60) * j;
            var p1 = this.getPoint(radian,radius - 3);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
    },
    drawing : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Core Drawing 
        this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.ctx.beginPath();
        this.ctx.arc(rx,ry,radius,0,2 * Math.PI);
        var radian = (Math.PI * 2 / 12) * this.count;
        var p = this.getPoint(radian,radius);
        this.drawingMarks();
        //
        this.ctx.moveTo(rx, ry);
        this.ctx.arc(rx,ry,2,0,Math.PI*2);
        //
        var date = new Date();
        //Hour Wheel
        var hours = date.getHours();
        radian = (Math.PI * 2 / 12) * (hours - 12);
        var p1 = this.getPoint(radian - Math.PI/2,radius-25);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p1.x , ry + p1.y);
        //Minute Wheel
        var minutes = date.getMinutes();
        radian = (Math.PI * 2 / 60) * minutes;
        var p2 = this.getPoint(radian - Math.PI/2,radius-15);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p2.x , ry + p2.y);
        //Second Wheel
        var seconds = date.getSeconds();
        radian = (Math.PI * 2 / 60) * seconds;
        var p3 = this.getPoint(radian - Math.PI/2,radius);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p3.x , ry + p3.y);
        this.ctx.stroke();
    },
    getPoint : function(radian,radius){
        var x = Math.cos(radian) * radius;
        var y = Math.sin(radian) * radius;
        return {x : x , y : y};
    },
    start : function(){
        //this.drawing();
        setInterval($.proxy(this.drawing,this),this.interval);
    }
};

function globalToLocal(canvas, x, y) {
  var bbox = canvas.getBoundingClientRect();
  var x = x - bbox.left * (canvas.width / bbox.width);
    var y = y - bbox.top  * (canvas.height / bbox.height);
    return {x: x, y : y};
}


$(function(){
    var c = new Clock();
    c.start();
});

完整版

Clock = function(){
    var jCanvas = $('<canvas width="450" height="300">');
    //jCanvas.on('mousemove',onMousemove);
    $(document.body).append(jCanvas);
    this.canvas = jCanvas[0];
    this.ctx = this.canvas.getContext('2d');
    this.ctx.strokeStyle = 'red';
    this.ctx.fillStyle = 'red';
    this.rect = {w:this.canvas.width,h:this.canvas.height,x:0,y:0};
    this.radius = 50;
    this.count = 1;
    this.interval = 1000;
};

Clock.prototype = {
    drawingMarks : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Hour Wheel Marks
        for(var i=1;i<=12;i++){
            var radian = (Math.PI * 2 / 12) * i;
            var p1 = this.getPoint(radian,radius - 8);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
        //Minute Wheel Marks
        for(var j=1;j<=60;j++){
            var radian = (Math.PI * 2 / 60) * j;
            var p1 = this.getPoint(radian,radius - 3);
            var p2 = this.getPoint(radian,radius);
            this.ctx.moveTo(rx + p1.x , ry + p1.y);
            this.ctx.lineTo(rx + p2.x , ry + p2.y);
        }
    },
    drawing : function(){
        var radius = this.radius;
        var rx = radius;
        var ry = radius;
        //Core Drawing 
        this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.ctx.beginPath();
        this.ctx.arc(rx,ry,radius,0,2 * Math.PI);
        var radian = (Math.PI * 2 / 12) * this.count;
        var p = this.getPoint(radian,radius);
        this.drawingMarks();
        //
        this.ctx.moveTo(rx, ry);
        this.ctx.arc(rx,ry,2,0,Math.PI*2);
        //
        var date = new Date();
        var hours = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        //Hour Wheel
        radian = (Math.PI * 2 / 12) * (hours - 12) + (Math.PI * 2 / 12) * (minutes / 60);
        var p1 = this.getPoint(radian - Math.PI/2,radius-25);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p1.x , ry + p1.y);
        //Minute Wheel
        radian = (Math.PI * 2 / 60) * minutes + (Math.PI * 2 / 12 / 60 / 60) * seconds;;
        var p2 = this.getPoint(radian - Math.PI/2,radius-15);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p2.x , ry + p2.y);
        //Second Wheel
        radian = (Math.PI * 2 / 60) * seconds;
        var p3 = this.getPoint(radian - Math.PI/2,radius);
        this.ctx.moveTo(rx, ry);
        this.ctx.lineTo(rx + p3.x , ry + p3.y);
        this.ctx.stroke();
    },
    getPoint : function(radian,radius){
        var x = Math.cos(radian) * radius;
        var y = Math.sin(radian) * radius;
        return {x : x , y : y};
    },
    start : function(){
        //this.drawing();
        setInterval($.proxy(this.drawing,this),this.interval);
    }
};

function globalToLocal(canvas, x, y) {
  var bbox = canvas.getBoundingClientRect();
  var x = x - bbox.left * (canvas.width / bbox.width);
    var y = y - bbox.top  * (canvas.height / bbox.height);
    return {x: x, y : y};
}


$(function(){
    var c = new Clock();
    c.start();
});

SEO

如何/怎么 截图 画箭头实现,类似 QQ 那种截图后画箭头的功能。
如何/怎么 画一个闹钟展现在页面/界面上。

最后

以上这些是我个人总结的一些肤浅的知识,如果有不对的地方还望多多赐教,谢谢。

猜你喜欢

转载自blog.csdn.net/littlebrain4solving/article/details/78958611