【Canvas】js用canvas绘制一个钟表时钟动画效果

学习JavaScript的看过来,有没有兴趣用Canvas画图呢,可以画很多有趣的事物,自由发挥想象,收获多多哦,旋转角度绘图这个重点掌握到了吗,这里有一个例子,如何用canvas画钟表时钟动图效果,接下来开始讲,边学边做。

1. 设计页面

首先,做好一个页面,开始写布局,页面源代码如下,看起来很简单吧

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport"  content="width=device-width, initial-scale=1.0"/>
		<title>Ballet Clock</title>
		<style>
			.clock{
				display: inherit;
				width: 70vw;
				height: 70vw;
				margin: auto;
				position: relative;
				margin-top: 10vw;
			}
			
			.clock img{
				position: absolute;
				left: 0;
				top: 0;
				width: 100%;
				height: 100%;
			}
		</style>
	</head>
	<body>
		<div>
			<div class="clock">
				<img id="clock"/>
				<img id="hour"/>
				<img id="minute"/>
				<img id="second"/>
			</div>
		</div>
		<script>
			//引入模块
			import BalletClock from './ballet_clock.js';
			
			window.onload=()=>{
				//加载脚本...
			}
		</script>
	</body>
</html>

2. 加载脚本

接下来,页面的加载脚本像这样写的,代码如下,应该看得明白吧

const { clock,hour,minute,second } = ((args)=>{
let e={};
	args.forEach(a=>e[a]=document.getElementById(a));
	return e;
})('clock,hour,minute,second'.split(','));
//创建一个模块对象
let bc = new BalletClock();
bc.start({
	bgImg:clock,
	hourImg:hour,
	minuteImg:minute,
	secondImg:second
	//...传入模块参数
},window)

3. 实现模块

发现了吗,有个引用的模块ballet_clock.js文件是没有的,需要自己去写一个,这时候要复杂一点,代码并不多

1. 初始化

先实现初始化的逻辑方法init(),代码如下,是绘制一个钟表图,很简单吧

export default class BalletClock{
	constructor(){
		
	}
	#init(config,window){
		const { document } = window;
		const { bgImg, hourImg, minuteImg, secondImg } = config;
		//这里创建一个画布 设置好宽高与图片元素益智
		let canvas = document.createElement('canvas');
		canvas.width=bgImg.width;
		canvas.height=canvas.width;
		//获取画布上下文对象(封装的可操作方法集合)
		let ctx = canvas.getContext('2d');
		const { width, height } = ctx.canvas;
		//表盘中心点
		let center = {
			x: width/2,
			y: height/2,
			r: width/2
		};
		//画表盘
		ctx.fillStyle=config.bgColor;
		ctx.arc(center.x,center.y,center.r,0,Math.PI*2);
		ctx.fill();
		//画刻度
		ctx.strokeStyle=config.foreColor;
		ctx.fillStyle=config.foreColor;
		ctx.textAlign='center';
		ctx.textBaseline='middle';
		ctx.font=`${config.fontSize}px sans-serif`;
		let r = center.r-config.fontSize;
		//旋转中心角度,将分布在不同角度位置的小时数画出来
		for(let a=0,hour=0; a<360; a+=30){
			let angle = (a-90)/180*Math.PI;
			let x = Math.cos(angle)*r;
			let y = Math.sin(angle)*r;
			ctx.fillText(hour==0?'12':hour.toString(),x+center.x,y+center.y);
			hour++;
		}
		bgImg.src=canvas.toDataURL();
		//画时针 最后设置到图片元素钟
		ctx.lineCap='round';
		ctx.lineWidth=config.fontSize/2;
		ctx.clearRect(0,0,width,height);
		ctx.beginPath();
		ctx.moveTo(center.x,center.y);
		ctx.lineTo(center.x,center.y*0.5);
		ctx.stroke();
		ctx.lineWidth=1;
		ctx.beginPath();
		ctx.arc(center.x,center.y,config.fontSize,0,Math.PI*2);
		ctx.fill();
		hourImg.src=canvas.toDataURL();
		//画分针 最后设置到图片元素钟
		ctx.lineWidth=config.fontSize/4;
		ctx.clearRect(0,0,width,height);
		ctx.beginPath();
		ctx.moveTo(center.x,center.y);
		ctx.lineTo(center.x,center.y*0.2);
		ctx.stroke();
		minuteImg.src=canvas.toDataURL();
		//画秒针 最后设置到图片元素钟
		ctx.strokeStyle='#f85';
		ctx.lineWidth=config.fontSize/6;
		ctx.clearRect(0,0,width,height);
		ctx.beginPath();
		ctx.moveTo(center.x,center.y);
		ctx.lineTo(center.x,center.y*0.1);
		ctx.stroke();
		secondImg.src=canvas.toDataURL();
	}
	start(config,window){
		//这里实现开始动画逻辑...
	}
}

💡关于绘图中的角度如何定,看上面代码中用到了相关函数是Math.cos()Math.cos(),其用法类似于在初中数学的“勾股定理”,如还不清楚,就要复习一下数学了,要理解透彻哦,再讲讲如下代码:

let angle = (a-90)/180*Math.PI;
let x = Math.cos(angle)*r;
let y = Math.sin(angle)*r;
其中a才是角度,angle是弧度,r是圆的半径,这样可以计算出xy在圆边上的哪个位置,圆中心点是**(0,0)**哈~这样好理解的

2. 开始动画

接着实现动画的逻辑方法start(),代码如下,能看懂最好

export default class YinAndYangTaiChiDiagram{
		
	constructor(){
		
	}
	
	#init = (config,window) => {
		//初始化,绘制钟表...
	}
	
	//这里实现开始动画逻辑
	start(config,window){
		const { bgImg, hourImg, minuteImg, secondImg } = config;
		this.#init(Object.assign({
			fontSize:18,
			bgColor:'#000',
			foreColor:'#fff',
		},config),window);
		//更新显示的逻辑 因调用多次 故写在一个函数中
		const updateAnimation = ()=>{
			let date = new Date();
			//定义一个时分秒的数据
			let  d = {
				hour: date.getHours()%12,
				minute: date.getMinutes(),
				second: date.getSeconds()
			};
			//求秒针的角度
			let angle = d.second/60*360;
			secondImg.style.transform=`rotate(${angle}deg)`;
			//求分针的角度
			angle = d.minute/60*360;
			minuteImg.style.transform=`rotate(${angle}deg)`;
			//求时针的角度
			angle = d.hour/12*360+d.minute/60*30;
			hourImg.style.transform=`rotate(${angle}deg)`;
			//考虑处理性能 调用此处 可避免没必要的更新
			window.requestAnimationFrame(()=>{
				//延迟更新  每一秒就更新
				setTimeout(()=>updateAnimation(),1000)
			});
		};
		//开始更新
		updateAnimation();
	}
}

4. 运行效果

最后,打开浏览器运行该网页,没出问题的话,就能看到期待的钟表图,带动画效果,效果图如下
请添加图片描述

💡 此钟表好看吗,自己动手,试试修改网页上的配置参数如下,按自己的爱好定制自己喜欢颜色的钟表吧

bc.start({
	//...传入配置参数
	fontSize:18,
	bgColor:'#000',
	foreColor:'#fff',
},window)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

TA远方

谢谢!收到你的爱╮(╯▽╰)╭

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

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

打赏作者

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

抵扣说明:

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

余额充值