【前端html/js】使用canvas实现实时时钟

【前端html/js】使用canvas实现实时时钟

实现效果
效果

  • 代码如下

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>飛宇时钟</title>
</head>
<body>
	<canvas id="canvas" width="800" height="600"></canvas>

	<script type="text/javascript">
		"use strict ";
		function getDatetime(){
			let da = new Date();
			let hours = da.getHours();
			hours=hours>12?hours-12:hours;
			let minute = da.getMinutes();
			let second = da.getSeconds();
			return [hours,minute,second];
		}
	</script>
	<script type="text/javascript">
		let canvas = document.getElementById('canvas');
		let ctx = canvas.getContext('2d');
		
		// 绘制刻度函数
		function scaleRender(deg,start,end,bw,color){
			ctx.beginPath();
			ctx.rotate(deg);		// 旋转
			ctx.moveTo(start,0);
			ctx.lineTo(end,0);
			ctx.lineWidth=bw;
			ctx.strokeStyle=color;
			ctx.stroke();
			ctx.closePath();
			ctx.restore();
			ctx.save();
		}
		function initClockBasicInfo(){
			// 圆的中心的 x 坐标,圆的中心的 y 坐标,圆的半径,起始角,以弧度计,结束角,以弧度计。可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针
			// ctx.arc(400,300,200,0,2*Math.PI)
			ctx.beginPath();
			ctx.arc(0,0,200,0,2*Math.PI)
			ctx.strokeStyle="darkgrey";
			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(180,0);
				ctx.lineTo(190,0);
				ctx.lineWidth = 2;
				ctx.strokeStyle="orangered"
				ctx.stroke()
				ctx.closePath();
			}
			
			ctx.restore();
			ctx.save();
	
			// 绘制时钟刻度
			for(let i=0;i<12;i++){
				ctx.rotate(Math.PI/6)
				ctx.beginPath();
				ctx.moveTo(180,0);
				ctx.lineTo(200,0);
				ctx.lineWidth = 10;
				ctx.strokeStyle="darkgray"
				ctx.stroke()
				ctx.closePath();
			}
			
			ctx.restore();
			ctx.save();
			
			// 绘制时钟刻度数字
			for(let i=1;i<=12;i++){
				ctx.rotate((Math.PI/6));
				ctx.save();
				ctx.beginPath();
				ctx.translate(165,-4);
				ctx.rotate(Math.PI/2-(Math.PI/6)*i);
				ctx.strokeStyle="skyblue"
				// ctx.strokeText((i,150,0)
				ctx.fillText(i, 0, 0);
				// ctx.stroke(); 
				ctx.closePath();
				
				ctx.restore();
			}
			ctx.restore();
			ctx.save();
		}
		
		// 初始化时钟
		function initClock(){
			ctx.clearRect(0,0,800,600);
			ctx.save();
			// 将画布移动画布中央
			ctx.translate(400,300);
			ctx.rotate(-Math.PI/2)
			ctx.save();
			
			initClockBasicInfo();
			
			let time = getDatetime();
			
			// 绘制秒针
			scaleRender(Math.PI/30*time[2],-30,170,2,"coral");
			// 绘制分针
			scaleRender(Math.PI/30*time[1]+2*Math.PI/3600*time[2],-20,150,3,"darkblue");// 根据分针的时间进行旋转
			// 绘制时针
			scaleRender(Math.PI/6*time[0]+2*Math.PI/(12*60)*time[1] + 2*Math.PI/(12*3600)*time[2],
			-10,140,3,"darkslategray");// 根据时针的时间进行旋转
			
			// 
			ctx.beginPath();
			ctx.arc(0,0,2,0,Math.PI*2);
			ctx.strokeStyle="red";
			ctx.fill();
			ctx.stroke();
			ctx.closePath();
			
			ctx.restore();
			ctx.rotate(Math.PI/2)
			ctx.font="20px 微软雅黑";
			ctx.fillText(`${time[0]}:${time[1]}:${time[2]}`,-40,260);
			ctx.restore();
			
		}
		
		initClock();
		
		setInterval(function(){
			initClock();
		},1000);
		
	</script>

</body>
</html>

贴图版时钟效果

html代码

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
<meta name="full-screen" content="yes">
<meta charset="utf-8">
<title>飛宇时钟</title>
<script src="js/07clock.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
	*{margin: 0;padding: 0;box-sizing: border-box;}
	body{
		display: flex;flex-direction: row;
		justify-content: center;
		align-items: center;
	}
	@media screen and (max-width: 800px){
		body{
			width: 100vw;height: 100vh;overflow: overlay;
		}
	}
</style>
</head>
<body>
	<canvas id="clock" width="400" height="400"></canvas>
</body>
</html>

07clock.js 代码

window.onload = function(){
	const disk = './image/clock/';
	function getDatetime(){
		let da = new Date();
		let hours = da.getHours();
		let minute = da.getMinutes();
		let second = da.getSeconds();
		return [hours,minute,second];
	}
	function timeleng(a){
		return a.toString().padStart(2,'0');
	}
	
	const canvas = document.getElementById('clock');
	let ctx = canvas.getContext('2d');
	let time = getDatetime();
	
	
	const dataImgs = ['time-number.png','hours.png','minute.png','circle-bottom.png',
	'second.png','circle-center.png','circle-top.png'];
	let numberImg = new Image();
	let hourImg = new Image();
	let minuteImg = new Image();
	let secondImg = new Image();
	let circleBottomImg = new Image();
	let circleCenterImg = new Image();
	let circleTopImg = new Image();
	
	
	// 图片全部加载完毕
	numberImg.src=disk+dataImgs[0];
	numberImg.onload = function(){
		hourImg.src=disk+dataImgs[1];
		hourImg.onload = function(){
			minuteImg.src=disk+dataImgs[2];
			minuteImg.onload = function(){
				circleBottomImg.src=disk+dataImgs[3];
				circleBottomImg.onload = function(){
					secondImg.src=disk+dataImgs[4];
					secondImg.onload = function(){
						circleCenterImg.src=disk+dataImgs[5];
						circleCenterImg.onload = function(){
							circleTopImg.src=disk+dataImgs[6];
							circleTopImg.onload = function(){
								initClock();
								setInterval(()=>{
									time[0]=time[0]>12?time[0]-12:time[0];
									initClock();
									time = getDatetime();
								},16);
							}
						}
					}
				}
			}
		}
	};
	
	
	// 刻画刻度
	function kedu(deg,start,end,size=1){
		ctx.rotate(deg);
		ctx.beginPath();
		ctx.moveTo(start,0);
		ctx.lineTo(end,0);
		ctx.lineWidth=size;
		ctx.stroke();
		ctx.closePath();
	}
	
	// 图片中心旋转
	function centerRotateImage(x,y,deg,img,w,h){
		ctx.save();
		ctx.translate(x,y)
		ctx.rotate(Math.PI/180+deg);
		ctx.translate(-x,-y)
		ctx.beginPath();
		ctx.drawImage(img,0,0,w,h);
		ctx.closePath();
		ctx.restore();
	}
	
	// 初始化跟图片相关
	function timeImage(){
		ctx.save();
		let move = 18;
		ctx.translate(-move/2,-move/2)
		ctx.beginPath();
		ctx.drawImage(numberImg,0,0,numberImg.width+move,numberImg.height+move);
		ctx.closePath();
		ctx.restore();
		
		// 小时
		let hourRotate = Math.PI/30*3 + Math.PI/6*time[0] + Math.PI/1800*time[1] + 2*Math.PI/(3600*60)*time[2];
		centerRotateImage(move/2+200-4,move/2+200-4,hourRotate,hourImg,hourImg.width+move,hourImg.height+move);
		
		// 分钟
		let minuteRotate = (-Math.PI/30*13 + Math.PI/180) + Math.PI/30*time[1] + 2*Math.PI/3600*time[2];
		centerRotateImage(move/2+200,move/2+200,minuteRotate,minuteImg,minuteImg.width+move,minuteImg.height+move);
		
		// 底部
		centerRotateImage(move/2+200-4,move/2+200-4,0,circleBottomImg,circleBottomImg.width+move,circleBottomImg.height+move);
		
		// 秒
		let secondRotate=(-Math.PI/30*4 + Math.PI/3600*8) + Math.PI/30*time[2]  ;
		centerRotateImage(move/2+200,move/2+200,secondRotate,secondImg,secondImg.width+move,secondImg.height+move);
		
		// 中顶部
		centerRotateImage(move/2+200-4,move/2+200-4,0,circleCenterImg,circleCenterImg.width+move,circleCenterImg.height+move);
		centerRotateImage(move/2+200-4,move/2+200-4,0,circleTopImg,circleTopImg.width+move,circleTopImg.height+move);
	}
	
	// 初始化时钟
	function initClock(){
		ctx.clearRect(0,0,400,400);
		ctx.save();
		ctx.translate(200,200);
		ctx.save();
		
		ctx.beginPath();
		ctx.arc(0,0,192,0,Math.PI*2);
		ctx.lineWidth=5;
		ctx.stroke();
		ctx.closePath();
		
		ctx.restore();
		ctx.save();
		
		ctx.textAlign="center";
		// 绘制秒钟刻度
		for(let j=0;j<60;j++){
			kedu(Math.PI/30,178,190);
		}
		ctx.restore();
		ctx.save();
		
		ctx.textAlign="center";
		
		// 绘制分钟刻度
		for(let j=0;j<12;j++){
			kedu(Math.PI/6,170,190,6);
		}
		
		ctx.restore();
		ctx.restore();
		ctx.save();
		//  初始化跟图片相关
		timeImage();
		
	}
	
}

素材下载

-素材下载地址: https://github.com/finnfy/study/tree/master/canvas/image/clock

演示地址

https://www.0fy0.com/clock.html

演示效果

github
github贴图版

写于:2022年1月8日
作者QQ:420318184
邮箱:fy@0fy0.com

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飛之宇

你的支持是我们的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值