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 坐标用于在画布上对绘画进行定位。鼠标移动的矩形框上,显示定位坐标。
Canvas - 路径
在Canvas上画线,我们将使用以下两种方法:
moveTo(x,y) 定义线条开始坐标
lineTo(x,y) 定义线条结束坐标
绘制线条我们必须使用到 "ink" 的方法,就像stroke().
定义开始坐标(0,0), 和结束坐标 (200,100)。然后使用 stroke() 方法来绘制线条:
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().
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():
如下:
使用 "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 的文字(空心):
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():
来操作一个:
创建一个线性渐变。使用渐变填充矩形:
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():
实例
创建一个径向/圆渐变。使用渐变填充矩形:
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 绘制时钟的主要内容,如果未能解决你的问题,请参考以下文章