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 Base64编码和解码,实现URL参数传递。
Sep 18 Javascript
jquery 图片截取工具jquery.imagecropper.js
Apr 09 Javascript
JS使用oumousemove和oumouseout动态改变图片显示的方法
Mar 31 Javascript
实现非常简单的js双向数据绑定
Nov 06 Javascript
AngularJS入门教程之更多模板详解
Aug 19 Javascript
老生常谈JQuery data方法的使用
Sep 09 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
Apr 12 Javascript
vue项目搭建以及全家桶的使用详细教程(小结)
Dec 19 Javascript
从0到1构建vueSSR项目之node以及vue-cli3的配置
Mar 07 Javascript
vue路由教程之静态路由
Sep 03 Javascript
Vue中axios拦截器如何单独配置token
Dec 27 Javascript
详解Typescript 内置的模块导入兼容方式
May 31 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
php echo, print, print_r, sprintf, var_dump, var_expor的使用区别
2013/06/20 PHP
php获取文章上一页与下一页的方法
2014/12/01 PHP
php判断文件夹是否存在不存在则创建
2015/04/09 PHP
如何使用PHP对网站验证码进行破解
2015/09/17 PHP
php简单解析mysqli查询结果的方法(2种方法)
2016/06/29 PHP
利用WebBrowser彻底解决Web打印问题(包括后台打印)
2009/06/22 Javascript
JQuery each()函数如何优化循环DOM结构的性能
2012/12/10 Javascript
Jquery网页出现的乱码问题的三种解决方法
2013/06/30 Javascript
js日期相关函数总结分享
2013/10/15 Javascript
移除AngularJS下URL中的#字符的方法
2015/06/19 Javascript
AngularJS基础 ng-show 指令简单示例
2016/08/03 Javascript
JSON与String互转的实现方法(Javascript)
2016/09/27 Javascript
AngularJS实践之使用NgModelController进行数据绑定
2016/10/08 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
WebSocket实现简单客服聊天系统
2017/05/12 Javascript
JavaScript+Canvas实现彩色图片转换成黑白图片的方法分析
2018/07/31 Javascript
node中的密码安全(加密)
2018/09/17 Javascript
微信小程序实现日历签到
2020/09/21 Javascript
Linux系统上Nginx+Python的web.py与Django框架环境
2015/12/25 Python
可能是最全面的 Python 字符串拼接总结【收藏】
2018/07/09 Python
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
python中利用numpy.array()实现俩个数值列表的对应相加方法
2019/08/26 Python
Python Numpy库常见用法入门教程
2020/01/16 Python
Jupyter Notebook远程登录及密码设置操作
2020/04/10 Python
tensorflow 动态获取 BatchSzie 的大小实例
2020/06/30 Python
Python中flatten( ),matrix.A用法说明
2020/07/05 Python
香港彩色隐形眼镜在线商店:Stunninglens(全球免费送货)
2019/05/10 全球购物
SQL语言面试题
2013/08/27 面试题
自荐信格式的六要素
2013/09/21 职场文书
经理秘书岗位职责
2013/11/14 职场文书
医科大学生的自我评价
2013/12/04 职场文书
个人求职信范文分享
2014/01/06 职场文书
领导班子群众路线与四风问题对照检查材料思想汇报
2014/10/11 职场文书
违纪开除通知书
2015/04/25 职场文书
python 实现两个变量值进行交换的n种操作
2021/06/02 Python
Java 多态分析
2022/04/26 Java/Android