• 【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 Clocktitle>
    		<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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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){
    		//这里实现开始动画逻辑...
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    💡关于绘图中的角度如何定,看上面代码中用到了相关函数是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();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    4. 运行效果

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

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

    bc.start({
    	//...传入配置参数
    	fontSize:18,
    	bgColor:'#000',
    	foreColor:'#fff',
    },window)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

  • 相关阅读:
    JVM-垃圾回收
    SQL优化
    基于android平台下的猎聘校园系统的设计与实现
    (Java)Mybatis学习笔记(四)
    Redis进阶
    百度百科怎么修改词条内容?
    抖音直播招聘报白企业人力资源公司多渠道展示职位
    最新版nacos 2.2.3服务注册与发现版本依赖问题
    【pytorch源码分析--torch执行流程与编译原理】
    【云原生】前后端分离项目下 如何优雅的联调程序?
  • 原文地址:https://blog.csdn.net/zs1028/article/details/128081214