js基于canvas实现时钟组件


Posted in Javascript onFebruary 07, 2021

canvas一直是前端开发中不可或缺的一种用来绘制图形的标签元素,比如压缩上传的图片、比如刮刮卡、比如制作海报、图表插件等,很多人在面试的过程中也会被问到有没有接触过canvas图形绘制。

定义

canvas元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
canvas标签只是图形容器,您必须使用脚本来绘制图形。

浏览器支持

Internet Explorer 9、Firefox、Opera、Chrome 和 Safari 支持

那么本篇文章就通过一个时钟组件来熟悉使用一下关于canvas的api。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>canvas时钟</title>
<style>
*{margin:0;padding:0;}
body{text-align:center;padding-top:100px;}
</style>
</head>
<body>
<canvas id="clock" width="200px" height="200px"></canvas>
<script>
(function(win){
	function DrawClock(options){
		this.canvas = options.el;
		this.ctx  = this.canvas.getContext('2d');//方法返回一个用于在画布上绘图的环境
		this.width = this.ctx.canvas.width;
		this.height = this.ctx.canvas.height;
		this.r   = this.width / 2;
		this.rem  = this.width / 200;
		this.digits = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];

	  var self  = this;
	  self.init();
	  setInterval(function(){
	  	self.init();
	  }, 1000);
	}

	DrawClock.prototype = {
		init: function(){
			var ctx = this.ctx;
			ctx.clearRect(0, 0, this.width, this.height);  //在给定的矩形内清除指定的像素
			var now = new Date();
			var hours = now.getHours();
			var minutes = now.getMinutes();
			var seconds = now.getSeconds();

			var hour = hours >= 12 ? hours - 12 : hours;
			var minute = minutes + seconds / 60;

			this.drawBackground();
			this.drawHour(hour, minute);
			this.drawMinute(minute);
			this.drawSecond(seconds);
			this.drawDot();
			ctx.restore();
		},
		drawBackground: function(){
			var ctx = this.ctx;
			var self = this;
			ctx.save();
			ctx.translate(this.r, this.r);     //重新映射画布上的 (0,0) 位置
			ctx.beginPath();
			ctx.lineWidth = 8 * this.rem;
			ctx.arc(0, 0, this.r - ctx.lineWidth / 2, 0, 2 * Math.PI, false);  //创建弧/曲线(用于创建圆形或部分圆)
			ctx.stroke();
			ctx.font = 16 * this.rem + "px Arial";//设置或返回文本内容的当前字体属性
			ctx.textAlign = "center";       //设置或返回文本内容的当前对齐方式
			ctx.textBaseline = "middle";      //设置或返回在绘制文本时使用的当前文本基线
			this.digits.forEach(function(number, i){
				var rad = 2 * Math.PI / 12 * i;
				var x = Math.cos(rad) * (self.r - 33 * self.rem);
				var y = Math.sin(rad) * (self.r - 33 * self.rem);
				ctx.fillText(number, x, y);    //在画布上绘制"被填充的"文本
			});

			//分钟的刻度,每分钟转6deg
			for (var i = 0; i < 60; i++){
				ctx.save();            //保存当前环境的状态
				ctx.rotate(6 * i * Math.PI / 180); //旋转当前绘图
				ctx.beginPath();          //起始一条路径,或重置当前路径
				ctx.moveTo(0, -82 * this.rem);   //把路径移动到画布中的指定点,不创建线条
				ctx.lineTo(0, -87 * this.rem);   //添加一个新点,然后在画布中创建从该点到最后指定点的线条
				ctx.closePath();          //创建从当前点回到起始点的路径
				ctx.strokeStyle = '#000';     //设置或返回用于笔触的颜色、渐变或模式
				ctx.lineWidth = 1 * this.rem;   //设置或返回当前的线条宽度
				ctx.stroke();           //绘制已定义的路径
				ctx.restore();           //返回之前保存过的路径状态和属性
			}
			//小时的刻度,每小时转30deg
			for (var i = 0; i < 12; i++){
				ctx.save();
				ctx.rotate(30 * i * Math.PI / 180);
				ctx.beginPath();
				ctx.moveTo(0, -79 * this.rem);
				ctx.lineTo(0, -87 * this.rem);
				ctx.closePath();
				ctx.strokeStyle = '#000';
				ctx.lineWidth = 2 * this.rem;
				ctx.stroke();
				ctx.restore();
			}
		},
		drawHour: function(hour, minute){
			var ctx = this.ctx;
			ctx.save();
			ctx.beginPath();
			var hRad = 2 * Math.PI / 12 * hour;
			var mRad = 2 * Math.PI / 12 / 60 * minute;
			ctx.rotate(hRad + mRad);
			ctx.lineWidth = 6 * this.rem;
			ctx.lineCap = "round";         //设置或返回线条的结束端点样式
			ctx.moveTo(0, 10 * this.rem);
			ctx.lineTo(0, -this.r / 2);
			ctx.stroke();
			ctx.restore();
		},
		drawMinute: function(minute){
			var ctx = this.ctx;
			ctx.save();
			ctx.beginPath();
			var rad = 2 * Math.PI / 60 * minute;
			ctx.rotate(rad);
			ctx.lineWidth = 3 * this.rem;
			ctx.lineCap = "round";
			ctx.moveTo(0, 10 * this.rem);
			ctx.lineTo(0, -this.r + 26 * this.rem);
			ctx.stroke();
			ctx.restore();
		},
		drawSecond: function(second){
			var ctx = this.ctx;
			ctx.save();
			ctx.beginPath();
			ctx.fillStyle = "#c14543";
			var rad = 2 * Math.PI / 60 * second;
			ctx.rotate(rad);
			ctx.moveTo(-3 * this.rem, 20 * this.rem);
			ctx.lineTo(3 * this.rem, 20 * this.rem);
			ctx.lineTo(1, -this.r + 26 * this.rem);
			ctx.lineTo(-1, -this.r + 26 * this.rem);
			ctx.fill();  //填充当前绘图(路径)
			ctx.restore();
		},
		drawDot: function(minute){
			var ctx = this.ctx;
			ctx.beginPath();
			ctx.fillStyle = "#fff";
			ctx.arc(0, 0, 3 * this.rem, 0, 2 * Math.PI, false);
			ctx.fill();
		}
	};

    win.DrawClock = DrawClock;
})(window);

new DrawClock({el: document.getElementById("clock")});
</script>
</body>
</html>

只要心中有丘壑,就能耕出二亩田!canvas时钟用到了canvas中大部分的api,通过学习canvas时钟的代码实现,很能了解canvas的属性和方法,同时,实现时钟效果时,用到了数学中的几何模型正弦sin和余弦cos以及弧度的计算方法,又重温了一把当年学数学时的许多乐趣,可谓是一举两得。

时钟效果图如下:

js基于canvas实现时钟组件

以上就是js基于canvas实现时钟组件的详细内容,更多关于canvas实现时钟组件的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript利用apply和arguments复用方法
Nov 25 Javascript
jQuery团购倒计时特效实现方法
May 07 Javascript
基于javascript实现文字无缝滚动效果
Mar 22 Javascript
json对象与数组以及转换成js对象的简单实现方法
Jun 24 Javascript
JavaScript新增样式规则(推荐)
Jul 19 Javascript
微信小程序图表插件(wx-charts)实例代码
Jan 17 Javascript
Vue.js实战之Vuex的入门教程
Apr 01 Javascript
Angular中封装fancyBox(图片预览)遇到问题小结
Sep 01 Javascript
Vue利用canvas实现移动端手写板的方法
May 03 Javascript
基于webpack4搭建的react项目框架的方法
Jun 30 Javascript
ES6基础之 Promise 对象用法实例详解
Aug 22 Javascript
vue实现的封装全局filter并统一管理操作示例
Feb 02 Javascript
nestjs中异常过滤器Exceptionfilter的具体使用
Feb 07 #Javascript
js实现类选择器和name属性选择器的示例步骤
Feb 07 #Javascript
vue如何使用rem适配
Feb 06 #Vue.js
如何管理Vue中的缓存页面
Feb 06 #Vue.js
JS中锚点链接点击平滑滚动并自由调整到顶部位置
Feb 06 #Javascript
一起深入理解js中的事件对象
Feb 06 #Javascript
手动实现vue2.0的双向数据绑定原理详解
Feb 06 #Vue.js
You might like
利用phpexcel把excel导入数据库和数据库导出excel实现
2014/01/09 PHP
由prototype_1.3.1进入javascript殿堂-类的初探
2006/11/06 Javascript
js 表单验证方法(实用)
2009/04/28 Javascript
基于jquery的finkyUI插件与Ajax实现页面数据加载功能
2010/12/03 Javascript
jquery调用wcf并展示出数据的方法
2011/07/07 Javascript
在JS中操作时间之getUTCMilliseconds()方法的使用
2015/06/10 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
2017/02/09 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
2017/02/10 Javascript
Windows下快速搭建NodeJS本地服务器的步骤
2017/08/09 NodeJs
如何从0开始用node写一个自己的命令行程序
2018/12/29 Javascript
javascript实现的时间格式加8小时功能示例
2019/06/13 Javascript
基于form-data请求格式详解
2019/10/29 Javascript
node实现mock-plugin中间件的方法
2019/12/25 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
Node.js API详解之 dgram模块用法实例分析
2020/06/05 Javascript
[03:33]TI9战队采访 - Infamous
2019/08/20 DOTA
Python中不同进制互相转换(二进制、八进制、十进制和十六进制)
2015/04/05 Python
python使用itchat库实现微信机器人(好友聊天、群聊天)
2018/01/04 Python
python 连接各类主流数据库的实例代码
2018/01/30 Python
python在线编译器的简单原理及简单实现代码
2018/02/02 Python
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
python特性语法之遍历、公共方法、引用
2018/08/08 Python
使用PIL(Python-Imaging)反转图像的颜色方法
2019/01/24 Python
在Django model中设置多个字段联合唯一约束的实例
2019/07/17 Python
Python 实现自动导入缺失的库
2019/10/29 Python
python创建子类的方法分析
2019/11/28 Python
教师自荐书
2013/10/08 职场文书
采购主管工作职责
2013/12/12 职场文书
师范生自我鉴定
2014/03/20 职场文书
企业委托书范本
2014/09/13 职场文书
乡镇党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
2014年环境整治工作总结
2014/12/10 职场文书
服务明星事迹材料
2014/12/29 职场文书
贷款承诺书
2015/01/20 职场文书
庐山导游词
2015/02/03 职场文书
2015高三毕业寄语赠言
2015/02/27 职场文书