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 装载iframe子页面,自适应高度
Mar 20 Javascript
javascript中使用css需要注意的地方小结
Sep 01 Javascript
JQuery中html()方法使用不当带来的陷阱
Apr 07 Javascript
jQuery取消ajax请求的方法
Jun 09 Javascript
Angularjs整合微信UI(weui)
Mar 15 Javascript
Jquery遍历select option和添加移除option的实现方法
Aug 26 Javascript
用JS动态设置CSS样式常见方法小结(推荐)
Nov 10 Javascript
深入理解Vue 的钩子函数
Sep 05 Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
Oct 31 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
May 08 Javascript
Vue 设置axios请求格式为form-data的操作步骤
Oct 29 Javascript
vue 动态添加的路由页面刷新时失效的原因及解决方案
Feb 26 Vue.js
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实现session自定义会话处理器的方法
2015/01/27 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
使用php自动备份数据库表的实现方法
2017/07/28 PHP
php实现等比例压缩图片
2018/07/26 PHP
JavaScript 实现模态对话框 源代码大全
2009/05/02 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
2013/01/15 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
2013/10/15 Javascript
js将json格式内容转换成对象的方法
2013/11/01 Javascript
js函数模拟显示桌面.scf程序示例
2014/04/20 Javascript
jQuery固定浮动侧边栏实现思路及代码
2014/09/28 Javascript
jQuery实现移动 和 渐变特效的点击事件
2015/02/26 Javascript
jQuery实现Email邮箱地址自动补全功能代码
2015/11/03 Javascript
jQuery Easyui 验证两次密码输入是否相等
2016/05/13 Javascript
AngularJS基础 ng-selected 指令简单示例
2016/08/03 Javascript
javascript设计模式之中介者模式学习笔记
2017/02/15 Javascript
Angularjs 实现移动端在线测评效果(推荐)
2017/04/05 Javascript
使用canvas进行图像编辑的实例
2017/08/29 Javascript
关于vue-router的beforeEach无限循环的问题解决
2017/09/09 Javascript
使用jquery Ajax实现上传附件功能
2018/10/23 jQuery
JS中通过url动态获取图片大小的方法小结(两种方法)
2018/10/31 Javascript
React+Antd+Redux实现待办事件的方法
2019/03/14 Javascript
Vue实现摇一摇功能(兼容ios13.3以上)
2021/01/26 Vue.js
[00:35]DOTA2上海特级锦标赛 Newbee战队宣传片
2016/03/03 DOTA
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
Python实现拷贝多个文件到同一目录的方法
2016/09/19 Python
Python使用win32com实现的模拟浏览器功能示例
2017/07/13 Python
python判断数字是否是超级素数幂
2018/09/27 Python
详解使用Python写一个向数据库填充数据的小工具(推荐)
2020/09/11 Python
运动会广播稿20字
2014/02/18 职场文书
师德演讲稿范文
2014/05/06 职场文书
欢迎横幅标语
2014/06/17 职场文书
销售竞赛活动方案
2014/08/23 职场文书
大学开学典礼新闻稿
2015/07/17 职场文书
windows安装python超详细图文教程
2021/05/21 Python
日元符号 ¥
2022/02/17 杂记
PostgreSQL出现死锁该如何解决
2022/05/30 PostgreSQL