一、简介:Canvas简介
? ? ??Canvas 自 HTML5 发布以来就受到了广泛的关注,但却很少在项目中使用,所以大部分前端攻城狮都只是知道,很少实践。canvas所具有的强大功能足以令人震撼。用canvas做了个简单的页面时钟,时钟可以实现动态展示时间的效果。
图1:时钟静态效果
? ? 很遗憾的是暂时无法上传视频到博客中,不过相信各位同学一步步做出来也可以看到动态的效果。
二、Canvas简单创建
? ? ? ? 作为HTML5的一个标签,直接在<body></body>中创建canvas标签即可。同其他标签一样,canvas标签中有三个核心的属性,分别是id,width,height。id作为标签的标志,当然是用于js获取dom元素啦,此处可不能使用class哦。而width,height是圈定画布的区域大小,正如插入的代码中的注释一样,此处的长宽设定值不同于style样式中的长宽,具体区别见注释中。当然自己实际进行操作后会将两者的不同区分的更清楚的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 此处需要特别注意的是,canvas中的width和height不同于style中的。canvas中表示的是画布中的内容的分辨率,就是如果其长宽设置成小于图片大小,则只展示圈定的部分。而style中是调节的整个内容尺寸的大小,不影响内容的完整性 -->
<canvas id="canvas1" width="800px" height="600px" style="width: 600px;height:900px;">
</canvas>
<script type="text/javascript">
let canvas1 = document.getElementById("canvas1");
//此处用于创建画笔,也就是我们绘制图形的工具
let ctx1 = canvas1.getContext("2d");
</script>
</body>
</html>
三、时钟表盘、小时分钟刻度的绘制
? ? ? ? 在完成创建canvas标签并给定相关的属性,js获取到dom元素,创建好画笔三步后。接下来就是进行相关的图形绘制了。由于默认的坐标位于页面的右上角,为了便于操作,我们需要将坐标原点进行移动,移动到我们表盘的圆心。以下就是本小节相关的代码,所有的代码如果需要内置到<script>标签中哦。
//移动原点到画布的中心
ctx.translate(400, 300);
//绘制表盘圆,每次进行绘制的时候,都要进行路径的开始和结束。
ctx.beginPath();
ctx.arc(0, 0, 200, 0, 2 * Math.PI);
ctx.strokeStyle = "pink";
ctx.lineWidth = 10;
ctx.stroke();
//本次绘制路径结束标志
ctx.closePath();
//绘制完成后对画笔进行重置和储存。
ctx.restore();
ctx.save();
//分针刻度绘制;使用for循环对绘制的分针刻度绕圆心进行旋转复制
for (let j = 0; j < 60; j++) {
ctx.rotate(Math.PI / 30);
ctx.beginPath();
//线段的起点
ctx.moveTo(175, 0);
//线段经过的点
ctx.lineTo(190, 0);
ctx.strokeStyle = "dark";
ctx.lineWidth = 4;
ctx.stroke();
ctx.closePath();
}
ctx.restore();
ctx.save();
//绘制时针刻度,按照计算的刻度完成固定的旋转次数。
for (let i = 0; i < 12; i++) {
ctx.rotate(Math.PI / 6);
ctx.beginPath();
ctx.moveTo(175, 0);
ctx.lineTo(200, 0);
ctx.lineWidth = 8;
ctx.strokeStyle = "Pink";
ctx.stroke();
ctx.closePath();
}
ctx.restore();
ctx.save();
? ? ? ?经过上述代码的运行,可以得到下面的效果;是不是感觉初具规模呢?当然,表盘和刻度的的颜色样式可以根据需要自行进行修改。结束了这一小节,下面就要进行时钟的三个指针的绘制啦。
图2:时钟过程效果1
四、时,分,秒指针的绘制和时间的获取
? ? ? 此部分直接上代码啦,具体的说明尽量在代码的注释。
//创建获取时间
let time = new Date();
let hour = time.getHours();
let min = time.getMinutes();
let sec = time.getSeconds();
//表盘只有12个小时的刻度,但是一天有24小时,用三目运算符进行修改。
hour = hour > 12 ? hour - 12 : hour;
//此处通过控制台检查获取时间是否正确。
console.log(hour, '时', min, "分", sec, "秒");
? ? ? ? ? ? ? ? ? ?时、分、秒指针的绘制。
//绘制秒针
ctx.beginPath();
//此处的旋转需要带上sec变量,即获取的秒钟,每次刷新后既可以实现动态走动。
ctx.rotate(2 * Math.PI / 60 * sec);
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(160, 0);
ctx.strokeStyle = "grey";
ctx.lineWidth = 6;
ctx.lineCap = "round";
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
//绘制分针
ctx.beginPath();
//好好思考一下,此处的运算表达式为么这样写呢?下面的时针表达式又是如何来的呢?
ctx.rotate(2 * Math.PI / 60 * min + 2 * Math.PI / 3600 * sec);
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(135, 0);
ctx.strokeStyle = "";
ctx.lineCap = "round";
ctx.lineWidth = 8;
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
//绘制时针
ctx.beginPath();
ctx.rotate(2 * Math.PI / 12 * hour + 2 * Math.PI / 720 * min + 2 * Math.PI / 3600 * sec);
ctx.beginPath();
ctx.moveTo(-10, 0);
ctx.lineTo(100, 0);
ctx.strokeStyle = "deepskyBlue"
ctx.lineWidth = 9;
ctx.lineCap = "round";
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
? ? ? ?写到此处,时钟的整体轮廓就已经基本完成了,一边写一边查看效果是前端应该有的良好习惯哦。那我们来看看写到此处应该有什么效果吧。写到此处,每次刷新后可以看到时钟的秒针发生了转动,但是通过控制台打印的本地时间发现并不符合。怎么解决这个问题呢?
? ? 可以通过在开始的坐标原点平移处将表盘的绘制路径旋转45度,代码如下,当然具体的旋转度数要以实际的相差为准。
//移动原点到画布的中心
ctx.translate(400, 300);
//校正秒针,将圆盘进行适当的旋转。
ctx.rotate(-2 * Math.PI / 4);
? ? 最后在画布的圆心为时钟加上一个圆形小盖子,直接绘制一个半径为10的圆形就好了。至此,时钟的所有画布上的静态组件全部绘制完成了。可是,目前只有通过每次刷新才能实现时钟的运动,有没有什么方式来实现时钟的自动转动呢?先自己思考一下哦。
//给圆的中心加个圈
ctx.beginPath();
ctx.arc(0, 0, 12, 0, 2 * Math.PI)
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
ctx.restore();
ctx.restore();
五、时钟动态效果的创建?
? ? ? ? ? 通过创建一个函数将上述所有代码囊括,在对本函数使用setInterval()方法设定1000ms的周期就可以实现时钟的运转了。先自己动手操作一下吧,本文的结束附上时钟的全部源代码。
六、总结
? ? ? ? 坦诚的说,这个时钟的画布元素比较少,只有简单的表盘、刻度、指针以及小盖子。后续还可以创建一些文字和阴影效果进行丰富,比如可以给指针创建渐变色,阴影等效果。所有的动态效果均是由javascript创建,后续也可以增添更多的新功能。关于canvas的学习,大可不必记住所有的属性方法,需要时直接去查询相关的中文文档会更好。
源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas1" width="800px" height="600px">
</canvas>
<script type="text/javascript">
let canvas1 = document.querySelector("#canvas1");
let ctx = canvas1.getContext("2d");
//保留画笔的设置
function renderClock() {
//此指令的目的就是清除划定区域内的所有像素元素。
ctx.clearRect(0, 0, 600, 800);
ctx.save();
//移动原点到画布的中心
ctx.translate(400, 300);
//校正秒针,将圆盘进行适当的旋转。
ctx.rotate(-2 * Math.PI / 4);
ctx.save();
//绘制表盘圆,每次进行绘制的时候,都要进行路径的开始和结束。
ctx.beginPath();
ctx.arc(0, 0, 200, 0, 2 * Math.PI);
ctx.strokeStyle = "pink";
ctx.lineWidth = 10;
ctx.stroke();
ctx.closePath();
//绘制完成后对画笔进行重置和储存。
ctx.restore();
ctx.save();
//分针刻度绘制;
for (let j = 0; j < 60; j++) {
ctx.rotate(Math.PI / 30);
ctx.beginPath();
//线段的起点
ctx.moveTo(175, 0);
//线段经过的点
ctx.lineTo(190, 0);
ctx.strokeStyle = "dark";
ctx.lineWidth = 4;
ctx.stroke();
ctx.closePath();
}
ctx.restore();
ctx.save();
//绘制时针刻度,按照计算的刻度完成固定的旋转次数。
for (let i = 0; i < 12; i++) {
ctx.rotate(Math.PI / 6);
ctx.beginPath();
ctx.moveTo(175, 0);
ctx.lineTo(200, 0);
ctx.lineWidth = 8;
ctx.strokeStyle = "Pink";
ctx.stroke();
ctx.closePath();
}
ctx.restore();
ctx.save();
//创建获取时间
let time = new Date();
let hour = time.getHours();
let min = time.getMinutes();
let sec = time.getSeconds();
//表盘只有12个小时的刻度,但是一天有24小时,用三目运算符进行修改。
hour = hour > 12 ? hour - 12 : hour;
//此处通过控制台检查获取时间是否正确。
console.log(hour, '时', min, "分", sec, "秒");
//绘制秒针
ctx.beginPath();
//此处的旋转需要带上sec变量,即获取的秒钟。
ctx.rotate(2 * Math.PI / 60 * sec);
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(160, 0);
ctx.strokeStyle = "grey";
ctx.lineWidth = 6;
ctx.lineCap = "round";
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
//绘制分针
ctx.beginPath();
ctx.rotate(2 * Math.PI / 60 * min + 2 * Math.PI / 3600 * sec);
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(135, 0);
ctx.strokeStyle = "";
ctx.lineCap = "round";
ctx.lineWidth = 8;
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
//绘制时针
ctx.beginPath();
ctx.rotate(2 * Math.PI / 12 * hour + 2 * Math.PI / 720 * min + 2 * Math.PI / 3600 * sec);
ctx.beginPath();
ctx.moveTo(-10, 0);
ctx.lineTo(100, 0);
ctx.strokeStyle = "deepskyBlue"
ctx.lineWidth = 9;
ctx.lineCap = "round";
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
//给圆的中心加个圈
ctx.beginPath();
ctx.arc(0, 0, 12, 0, 2 * Math.PI)
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
ctx.restore();
ctx.restore();
}
setInterval(function() {
renderClock()
}, 1000);
</script>
</body>
</html>
|