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

news/2024/11/16 14:35:27/

学习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)

在这里插入图片描述


http://www.ppmy.cn/news/66.html

相关文章

防火墙原理讲解——练习实验

♥️作者&#xff1a;小刘在C站 ♥️每天分享云计算网络运维课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放。 目录 一防火墙基础 二防火墙配置 三防火墙的高级应用 四.实验图纸 五.实验命令 一防火…

快速上手 TypeScript

快速上手 TypeScript ypeScript 简称 TS &#xff0c;既是一门新语言&#xff0c;也是 JS 的一个超集&#xff0c;它是在 JavaScript 的基础上增加了一套类型系统&#xff0c;它支持所有的 JS 语句&#xff0c;为工程化开发而生&#xff0c;最终在编译的时候去掉类型和特有的语…

考虑车轮纵向滑动的无人自行车平衡控制实现

摘要: 针对无人自行车在出现车轮纵向滑动下的平衡控制问题,提出一种将自行车车轮纵向滑动引入控制器的方法来实现在一定程度车轮纵向滑动下的无人自行车平衡运动控制。首先引入一种自行车线性变参数(linearparameter-varying,LPV)动力学模型,其次将卡尔曼滤波算法估算的自行…

基于样本平衡策略的多源迁移学习方法及其在乙烯精馏塔质量指标预测的应用

摘要: 基于数据驱动的工业过程建模需要依赖大量的标记良好的数据集,但与目标任务直接相关的标注数据往往是有限的。因此,可以利用与其具有相关性的辅助训练数据进行建模以实现任务迁移。然而,样本的不平衡问题一定程度上影响了迁移学习的性能表现。因此,提出了一种基于样本…

【数据结构与算法】LinkedList与链表

✨个人主页&#xff1a;bit me ✨当前专栏&#xff1a;数据结构 ✨每日一语&#xff1a;假如困境有解&#xff0c;何须心烦意乱&#xff1b;倘若困境无解&#xff0c;又何须郁郁寡欢。每个人都有两次生命&#xff0c;当你意识到你只有一次生命的时候&#xff0c;你的第二次生命…

Python使用magic判断文件MIME类型

文章目录官网安装使用判断文件的MIME类型支持中文的代码问题官网 GitHub - ahupp/python-magic: A python wrapper for libmagic 安装 pip install python-magic pip install python-magic-bin使用 判断文件的MIME类型 代码 # encodingutf-8 import magic #pip install pyt…

【每日一句】名人金句学英语(20221130)

原文&#xff1a; Life is a process of becoming, a combination of states we have to go through. Where people fail is that they wish to elect a state and remain in it. This is a kind of death. ‧Anas Nin 人生是一个转变的过程&#xff0c;是由我们必须经历的…

rubbitmq 图形界面使用 常用六种通信模式 Simple-Work-fanout-direct-topic-headers

阿里云服务器添加rubbitmq需要开启端口:rabbitmq阿里云服务器开放端口号 Rubbitmq地址: 服务器地址:15672 1.简单模式Simple 一个生产者、一个消费者&#xff0c;不需要设置交换机&#xff08;使用默认的交换机&#xff09; 2.工作队列模式Work Queue 一个生产者、多个消费者&a…