HTML canvas 绘制时钟

Posted web前端工程师兼UI设计师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTML canvas 绘制时钟相关的知识,希望对你有一定的参考价值。

什么是 canvas?

html5 <canvas> 元素用于图形的绘制,通过脚本 (通常是javascript)来完成.

<canvas> 标签只是图形容器,您必须使用脚本来绘制图形。

你可以通过多种方法使用 canvas 绘制路径,盒、圆、字符以及添加图像。


浏览器支持

表格中的数字表示支持 <canvas> 元素的第一个浏览器版本号。



创建一个画布(Canvas)

一个画布在网页中是一个矩形框,通过 <canvas> 元素来绘制.

注意: 默认情况下 <canvas> 元素没有边框和内容。

<canvas>简单实例如下:

html代码:

<canvas id="myCanvas" width="200" height="100"></canvas>


注意: 标签通常需要指定一个id属性 (脚本中经常引用), width 和 height 属性定义的画布的大小.

提示:你可以在HTML页面中使用多个 <canvas> 元素.

使用 style 属性来添加边框:

来个操作:

HTML代码:

<canvas id="myCanvas" width="200" height="100"style="border:1px solid #000000;"></canvas>


使用 JavaScript 来绘制图像

canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:

来个操作:

HTML代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d");ctx.fillStyle="#FF0000";ctx.fillRect(0,0,150,75);


解析:

首先,找到 <canvas> 元素:

var c=document.getElementById("myCanvas");

然后,创建 context 对象:

var ctx=c.getContext("2d");

getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

下面的两行代码绘制一个红色的矩形:

ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,150,75);

设置fillStyle属性可以是CSS颜色,渐变,或图案。fillStyle 默认设置是#000000(黑色)。

fillRect(x,y,width,height) 方法定义了矩形当前的填充方式。


Canvas 坐标

canvas 是一个二维网格。

canvas 的左上角坐标为 (0,0)

上面的 fillRect 方法拥有参数 (0,0,150,75)。

意思是:在画布上绘制 150x75 的矩形,从左上角开始 (0,0)。

坐标实例

如下图所示,画布的 X 和 Y 坐标用于在画布上对绘画进行定位。鼠标移动的矩形框上,显示定位坐标。

HTML canvas 绘制时钟


Canvas - 路径

在Canvas上画线,我们将使用以下两种方法:

  • moveTo(x,y) 定义线条开始坐标

  • lineTo(x,y) 定义线条结束坐标

绘制线条我们必须使用到 "ink" 的方法,就像stroke().


定义开始坐标(0,0), 和结束坐标 (200,100)。然后使用 stroke() 方法来绘制线条:

HTML canvas 绘制时钟

js代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d");ctx.moveTo(0,0);ctx.lineTo(200,100);ctx.stroke();


在canvas中绘制圆形, 我们将使用以下方法:

arc(x,y,r,start,stop)

实际上我们在绘制圆形时使用了 "ink" 的方法, 比如 stroke() 或者 fill().


HTML canvas 绘制时钟



js代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d");ctx.beginPath();ctx.arc(95,50,40,0,2*Math.PI);ctx.stroke();


Canvas - 文本

使用 canvas 绘制文本,重要的属性和方法如下:

  • font - 定义字体

  • fillText(text,x,y) - 在 canvas 上绘制实心的文本

  • strokeText(text,x,y) - 在 canvas 上绘制空心的文本

使用 fillText():

如下:

HTML canvas 绘制时钟

使用 "Arial" 字体在画布上绘制一个高 30px 的文字(实心):


js代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d");ctx.font="30px Arial";ctx.fillText("Hello World",10,50);


使用 strokeText():

如:

使用 "Arial" 字体在画布上绘制一个高 30px 的文字(空心):

HTML canvas 绘制时钟


js代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d");ctx.font="30px Arial";ctx.strokeText("Hello World",10,50);


Canvas - 渐变

渐变可以填充在矩形, 圆形, 线条, 文本等等, 各种形状可以自己定义不同的颜色。

以下有两种不同的方式来设置Canvas渐变:

  • createLinearGradient(x,y,x1,y1) - 创建线条渐变

  • createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变

当我们使用渐变对象,必须使用两种或两种以上的停止颜色。

addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是0至1.

使用渐变,设置fillStyle或strokeStyle的值为 渐变,然后绘制形状,如矩形,文本,或一条线。

使用 createLinearGradient():


来操作一个:

创建一个线性渐变。使用渐变填充矩形:

HTML canvas 绘制时钟


js代码:


var c=document.getElementById("myCanvas");var ctx=c.getContext("2d"); // 创建渐变var grd=ctx.createLinearGradient(0,0,200,0);grd.addColorStop(0,"red");grd.addColorStop(1,"white"); // 填充渐变ctx.fillStyle=grd;ctx.fillRect(10,10,150,80);


使用 createRadialGradient():

实例

创建一个径向/圆渐变。使用渐变填充矩形:

HTML canvas 绘制时钟

js代码:

var c=document.getElementById("myCanvas");var ctx=c.getContext("2d"); // 创建渐变var grd=ctx.createRadialGradient(75,50,5,90,60,100);grd.addColorStop(0,"red");grd.addColorStop(1,"white"); // 填充渐变ctx.fillStyle=grd;ctx.fillRect(10,10,150,80);


<canvas>标签定义图形,比如图表和其他图像,您必须使用脚本来绘制图形。

接下来我将跟大家分享如何在画布上(Canvas)画一个时钟。

先看下效果图:


图一:



图二:


下面是图一 ,图二的代码:


图一:


css代码:


<style type="text/css">

body{

    background-color: #c3c3c5;

}

            *{

                margin: 0;

                padding: 0;

            }

            .box{

                width: 300px;

                height: 300px;

                margin: 0 auto;

                margin-top: 100px;

               border-radius: 20px;

               box-shadow: 0 10px 5px rgba(0,0,0,0.2);

               background-image: linear-gradient(to bottom, #ffffff , #d5e5eb);

            }


        </style>


HTML代码:


<div class="box">

            <canvas id="canvas" width="300px" height="300px"></canvas>

        </div>


js代码:


<script type="text/javascript">

            var canvas = document.getElementById("canvas");

            var ctx = canvas.getContext('2d');

            run();

            setInterval(run,1000);

            function run(){

                var time = new Date();//获取现在时间

                var sec = time.getSeconds();//获取秒

                var min = time.getMinutes();//获取分钟

                var hour = time.getHours();//获取小时

                hour = hour>12 ? hour-12 : hour;

                ctx.clearRect(0,0,300,300);

                ctx.save();

                ctx.beginPath();

                ctx.lineWidth = 3;

                ctx.arc(150,150,130,0,2*Math.PI);

                var color = ctx.createRadialGradient(150,150,30,150,150,100);

                color.addColorStop(0.0,"#e9f3fc");

                color.addColorStop(1.0,"#e1eefa");

                ctx.fillStyle = color;

                ctx.fill();

                ctx.strokeStyle = "#a8bbce";

                ctx.stroke();

                ctx.restore();

                ctx.save();

                ctx.translate(150,150);

                for(var i=0; i<60; i++){

                    if(i%5 == 0){

                        ctx.beginPath();

                        ctx.moveTo(0,120);

                        ctx.lineTo(0,130);

                        ctx.lineWidth = 5;

                        ctx.strokeStyle = "#89a2b4";

                        ctx.stroke();

                        ctx.rotate(Math.PI/30);

                    }else{

                        ctx.beginPath();

                        ctx.moveTo(0,120);

                        ctx.lineTo(0,126);

                        ctx.lineWidth = 1;

                        ctx.strokeStyle = "cornflowerblue";

                        ctx.stroke();

                        ctx.rotate(Math.PI/30);

                    }


                }

                ctx.restore();

                //秒针

                ctx.save();

                ctx.translate(150,150);

                ctx.rotate(sec*Math.PI/30);

                ctx.beginPath();

                ctx.moveTo(0,30);

                ctx.lineTo(0,-120);

                ctx.lineWidth = 1;

                ctx.strokeStyle = "#7cd9fb";

                ctx.stroke();

                ctx.restore();

                //分针

                ctx.save();

                ctx.translate(150,150);

                ctx.rotate(sec*Math.PI/1800 + min*Math.PI/30);//每一秒再分60分,秒针走一刻度,分针要走1/60刻度,sec*(6*Math.PI/180)/60

                ctx.beginPath();

                ctx.moveTo(0,20);

                ctx.lineTo(0,-100);

                ctx.lineWidth = 2;

                ctx.strokeStyle = "#1dbaee";

                ctx.stroke();

                ctx.restore();

                //时针

                ctx.save();

                ctx.translate(150,150);

                ctx.rotate(min*Math.PI/360 + hour*Math.PI/6);//每一小时走过5个刻度线,60分钟,30deg,分成60份,30deg/60

                ctx.beginPath();

                ctx.moveTo(0,10);

                ctx.lineTo(0,-80);

                ctx.lineWidth = 3;

                ctx.strokeStyle = "#1aa9d8";

                ctx.stroke();

                ctx.restore();

                

// 中心大圆

ctx.save();

                ctx.translate(150,150);

ctx.beginPath();

ctx.arc(0,0,10,0,Math.PI*2);

ctx.fillStyle = "#84a3b8";

ctx.fill();

ctx.restore();

ctx.closePath();

// 中心圆小圆

                ctx.save();

                ctx.translate(150,150);

ctx.beginPath();

ctx.arc(0,0,7,0,Math.PI*2);

ctx.fillStyle = "#cee3ec";

ctx.fill();

ctx.restore();

ctx.closePath();

            }


        </script>


以上是图一代码 


图二:

css代码:


<style type="text/css">

#canvas{

width: 400px;

height: 400px;

/*border: solid 1px red;*/

display: block;

margin: 50px auto;

}
</style>



HTML代码:


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


js代码:


<script type="text/javascript">

var canvas = document.getElementById("canvas");

var context = canvas.getContext("2d");

// 绘制当前时间

var now = new Date();

drawClock(now.getHours(),now.getMinutes(),now.getSeconds());

// 定时器中完成时钟最后的效果

setInterval(function(){

// 清空画布

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

var now = new Date();

drawClock(now.getHours(),now.getMinutes(),now.getSeconds());

},1000);

function drawClock(h,m,s){

var r = canvas.width/2;

context.save();

context.translate(r,r);

// 外圆做为表盘

context.beginPath();

context.arc(0,0,r-10,0,Math.PI*2,true);

context.strokeStyle = "black";

context.lineWidth = 5;

context.stroke();

context.closePath();

// 绘制刻度

context.font="bolder 35px '微软雅黑'";

context.textAlign ='center';

context.textBaseline ="middle";

for(var i = 0 ;i<60;i++){

context.beginPath();

var x = Math.cos(Math.PI/180*i*6)*(r-40);

var y = Math.sin(Math.PI/180*i*6)*(r-40);

var pointWidth = 4;

var pointColor = "black";

if(i%5==0){

var n = (i/5+3)%12;

n = n==0?12:n;

context.fillText(n,x,y);

}else{

context.arc(x,y,pointWidth,0,Math.PI*2,true);

context.fillStyle = pointColor;

context.fill();

}

context.closePath();

}

// 时针

context.save();

context.rotate(Math.PI/180*(30*h+m/2));

context.beginPath();

context.lineTo(0,(r*0.1));

context.lineTo(0, -1*(r*0.5));

context.strokeStyle = "black";

context.lineWidth = 15;

context.lineCap = "round";

context.stroke();

context.restore();

context.closePath();

// 分针

context.save();

context.rotate(Math.PI/180*(6*m+s/10));

context.beginPath();

context.lineTo(0,(r*0.15));

context.lineTo(0, -1*(r*0.6));

context.strokeStyle = "black";

context.lineWidth = 10;

context.lineCap = "round";

context.stroke();

context.restore();

context.closePath();

// 秒针

context.save();

context.rotate(Math.PI/180*6*s);

context.beginPath();

context.lineTo(0,(r*0.2));

context.lineTo(0, -1*(r*0.8));

context.strokeStyle = "red";

context.lineWidth = 3;

context.stroke();

context.restore();

context.closePath();

// 中间的圆

context.beginPath();

context.arc(0,0,20,0,Math.PI*2);

context.fillStyle = "blue";

context.fill();

context.restore();

context.closePath();

}

</script>


总结:

我画了一个300*300的画布,

在将画布进行旋转的时候,

画布会沿着左上角进行转动,

所以,将画布移动到想要显示的中心点位置,

让图案进行旋转,转出刻度,

这里需要用到save()和restore(),

确保画布不会发生变动。 

秒针走过1秒走了6deg,即6*Math.PI/180。

要想实现分针走动,而不是跳动,就需要计算分针在一刻度内走的度数,

一刻度走了60秒,所以讲一刻度分了60分,

表示1秒钟分针走的度数,即(6*Math.PI/180)/60,

再加上分针走的度数就可以让分针准确走动。再来看时针,

时针一小时走了5个刻度,30deg,60分钟,

所以30deg/60就是时针在一分钟内走的度数,

也就是将1小时的角度划分了60份,

即Math.PI/360.读者可能会有疑问,

问什么不用秒去计算,即Math.PI/21600,

将1小时的角度划分了3600份,

这是因为用秒计算得到结果太小,

是0.00…的小数,偏差较大,无法让时针较准确走动,

                图二400*400要大一点原理都是一样的,大家也可以自己尝试。理解 这些基本原理,自己设计一个比较精美的钟表,由于明天开始三天假期(清明节) ,所以绘制的简单粗暴,最后祝大家回家路上一路平安   旅途愉快  要好好照顾自己天天开心,永远快乐啊。



以上是关于HTML canvas 绘制时钟的主要内容,如果未能解决你的问题,请参考以下文章

使用canvas绘制时钟

HTML canvas 绘制时钟

canvas学习笔记-绘制时钟

使用Canvas绘制简单的时钟控件

H5之canvas-绘制动态时钟

canvas绘制时钟