Canvas绘制一个时钟

Canvas:一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
博客地址:https://xiaofly.cn/post-details?id=627b9c9b5fcf765110cdcb6e

先上效果图:

先创建一个index.html,内容如下:

<!-- index.html -->
<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>Canvas绘制一个时钟</title><style>html, body {width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;}</style></head><body><canvas id="clock" width="400" height="400"></canvas><!-- 引入js --><script type="text/javascript" src="./index.js"></script></body>
</html>

上面代码没啥好讲的,重点是下面这段代码

<canvas id="clock" width="400" height="400"></canvas>

1、首先创建一个CanvasRenderingContext2D对象作为2D渲染的上下文

const $clock = document.getElementById('clock');
// 创建ctx对象
const ctx = $clock.getContext('2d');
// 定义圆心坐标(x, y)和半径r
const x = 200, y = 200, r = 150;

2、绘制表盘

渐变色:createLinearGradient(x0,y0,x1,y1)
创建线性的渐变对象,并使用addColorStop(stop,color) 方法规定颜色和位置。
绘制圆弧:arc(x, y, r, startAngle, endAngle, anticlockwise)
加粗样式以(x, y)为圆心,以r为半径,从 startAngle弧度开始到endAngle弧度结束。anticlosewise是布尔值,true表示逆时针,false表示顺时针。(默认是顺时针)

const lingrad = ctx.createLinearGradient(r, 0, -r, 0);
lingrad.addColorStop(0, '#242f37');
lingrad.addColorStop(1, '#48585c');
ctx.fillStyle = lingrad;
ctx.beginPath(); // 开始绘制
ctx.arc(x, y, r, 0, Math.PI * 2, true); // 绘制圆盘
ctx.fill(); // 填充

3、绘制时钟刻度

旋转坐标轴:rotate(angle)
旋转的角度(angle),它是顺时针方向的,以弧度为单位的值,旋转的中心为坐标原点。

// 这里需要将坐标点移到画布中心
ctx.translate(x, y);
for (let i = 0; i < 12; i++) {ctx.beginPath();ctx.strokeStyle = '#999';ctx.lineWidth = 3;ctx.rotate(Math.PI / 6); // Math.PI = 3.14 = 180°,180°中有6个小时,所以一个小时Math.PI/6ctx.moveTo(r-10, 0);ctx.lineTo(r-30, 0);ctx.stroke();
}

4、绘制分钟刻数

for (let i = 0; i < 60; i++) {if (i % 5 !== 0) { // 去掉与小时刻度重叠的部分ctx.beginPath();ctx.strokeStyle = '#536b7a';ctx.lineWidth = 2;ctx.moveTo(r-10, 0);ctx.lineTo(r-20, 0);ctx.stroke();}ctx.rotate(Math.PI / 30); // 180°中有30分钟,所以一分钟Math.PI/30
}

5、绘制时钟数字

ctx.font = '20px Arial';
ctx.fillStyle = '#aaa';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
for (let n = 1; n <= 12; n++) {const theta = (n - 3) * (Math.PI * 2) / 12;const x = r * 0.7 * Math.cos(theta);const y = r * 0.7 * Math.sin(theta);ctx.fillText(n, x, y);
}

6、绘制时针

saverestore 方法是用来保存和恢复 canvas 状态的

let hour = 3; // 假设为凌晨3点
ctx.save();
const thetaH = (hour - 3) * 2 * Math.PI / 12; // 获取时针旋转角度
ctx.rotate(thetaH);
ctx.beginPath();
ctx.moveTo(-15, -5);
ctx.lineTo(-15, 5);
ctx.lineTo(r * 0.5, 1);
ctx.lineTo(r * 0.5, -1);
ctx.fillStyle = '#555';
ctx.fill();
ctx.restore();

7、绘制分针

let minute = 30; // 假设现在是30分钟
ctx.save();
const thetaMin = (minute - 15) * 2 * Math.PI / 60; // 获取分针旋转角度
ctx.rotate(thetaMin);
ctx.beginPath();
ctx.moveTo(-15, -4);
ctx.lineTo(-15, 4);
ctx.lineTo(r * 0.8, 1);
ctx.lineTo(r * 0.8, -1);
ctx.fillStyle = '#666';
ctx.fill();
ctx.restore();

8、绘制秒针

let seconds = 40; // 假设现在是40秒钟
ctx.save();
const thetaS = (seconds - 15) * 2 * Math.PI / 60; // 获取秒针旋转角度
ctx.rotate(thetaS);
ctx.beginPath();
ctx.moveTo(-15, -3);
ctx.lineTo(-15, 3);
ctx.lineTo(r * 0.9, 1);
ctx.lineTo(r * 0.9, -1);
ctx.fillStyle = '#F66';
ctx.fill();
ctx.restore();

绘制秒针原点的凸起

ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI*2, true);
ctx.fillStyle = '#F66';
ctx.fill();

9、为了让钟表看起来更加真实,再给它加上阴影

// 阴影的x偏移
ctx.shadowOffsetX = -14;
// 阴影的y偏移
ctx.shadowOffsetY = 6;
// 阴影颜色
ctx.shadowColor = 'rgba(0,0,0,0.5)';
// 阴影的模糊半径
ctx.shadowBlur = 30;

10、现在最关键的让指针转动起来,所以我们需要用到requestAnimationFrame方法,用来重绘页面,得到连贯逐帧的动画,实现最佳的动画效果。

const $clock = document.getElementById('clock');
const ctx = $clock.getContext('2d');
const x = 200, y = 200, r = 150;window.requestAnimationFrame(function e() {// 每次执行完requestAnimationFrame后需要清除画布,不然出现重叠交错的现象ctx.clearRect(-10, 0, ctx.canvas.width, ctx.canvas.height);// 获取当前时间let date = new Date();let hours = date.getHours();let minutes = date.getMinutes();let seconds = date.getSeconds();hours = hours > 12 ? hours - 12 : hours;let hour = hours + minutes / 60;let minute = minutes + seconds / 60;ctx.save();// 这里放我们前面写的代码......window.requestAnimationFrame(e);
})

至此,一个能动的时钟就全部画好了。

最后附上index.js全部代码:

// index.js
const $clock = document.getElementById('clock');
const ctx = $clock.getContext('2d');
const x = 200, y = 200, r = 150;window.requestAnimationFrame(function e() {ctx.clearRect(-10, 0, ctx.canvas.width, ctx.canvas.height);// 获取当前时间let date = new Date();let hours = date.getHours();let minutes = date.getMinutes();let seconds = date.getSeconds();hours = hours > 12 ? hours - 12 : hours;let hour = hours + minutes / 60;let minute = minutes + seconds / 60;ctx.save();//绘制表盘底色const lingrad = ctx.createLinearGradient(r, 0, -r, 0);lingrad.addColorStop(0, '#242f37');lingrad.addColorStop(1, '#48585c');ctx.fillStyle = lingrad;ctx.beginPath();ctx.arc(x, y, r, 0, Math.PI * 2, true);ctx.fill();ctx.translate(x, y); // 将坐标原点移到画布中心// 绘制时钟刻数for (let i = 0; i < 12; i++) {ctx.beginPath();ctx.strokeStyle = '#999';ctx.lineWidth = 3;ctx.rotate(Math.PI / 6);ctx.moveTo(r-10, 0);ctx.lineTo(r-30, 0);ctx.stroke();}// 绘制分钟刻数for (let i = 0; i < 60; i++) {if (i % 5 !== 0) { // 去掉与小时刻度重叠的部分ctx.beginPath();ctx.strokeStyle = '#536b7a';ctx.lineWidth = 2;ctx.moveTo(r-10, 0);ctx.lineTo(r-20, 0);ctx.stroke();}ctx.rotate(Math.PI / 30);}// 绘制时钟数字ctx.font = '20px Arial';ctx.fillStyle = '#aaa';ctx.textAlign = 'center';ctx.textBaseline = 'middle';for (let n = 1; n <= 12; n++) {const theta = (n - 3) * (Math.PI * 2) / 12;const x = r * 0.7 * Math.cos(theta);const y = r * 0.7 * Math.sin(theta);ctx.fillText(n, x, y);}// 绘制时针ctx.save();const thetaH = (hour - 3) * 2 * Math.PI / 12;ctx.rotate(thetaH);ctx.beginPath();ctx.moveTo(-15, -5);ctx.lineTo(-15, 5);ctx.lineTo(r * 0.5, 1);ctx.lineTo(r * 0.5, -1);ctx.fillStyle = '#555';ctx.fill();ctx.restore();// 绘制分针ctx.save();const thetaMin = (minute - 15) * 2 * Math.PI / 60;ctx.rotate(thetaMin);ctx.beginPath();ctx.moveTo(-15, -4);ctx.lineTo(-15, 4);ctx.lineTo(r * 0.8, 1);ctx.lineTo(r * 0.8, -1);ctx.fillStyle = '#666';ctx.fill();ctx.restore();// 绘制秒针ctx.save();const thetaS = (seconds - 15) * 2 * Math.PI / 60;ctx.rotate(thetaS);ctx.beginPath();ctx.moveTo(-15, -3);ctx.lineTo(-15, 3);ctx.lineTo(r * 0.9, 1);ctx.lineTo(r * 0.9, -1);ctx.fillStyle = '#F66';ctx.fill();ctx.restore();ctx.restore();ctx.beginPath();ctx.arc(x, y, 5, 0, Math.PI*2, true);ctx.fillStyle = '#F66';ctx.fill();// 阴影的x偏移ctx.shadowOffsetX = -14;// 阴影的y偏移ctx.shadowOffsetY = 6;// 阴影颜色ctx.shadowColor = 'rgba(0,0,0,0.5)';// 阴影的模糊半径ctx.shadowBlur = 30;window.requestAnimationFrame(e);
})

完结

参考文档:
学习HTML5 Canvas这一篇文章就够了
Canvas绘制时钟

Canvas绘制一个时钟相关推荐

  1. android canvas 画按钮,Android 用Canvas轻松绘制一个时钟

    接下来这篇文章主要是结束如何轻松自定义一个View并使用Canvas绘制一个时钟的案例,话不多说先上图瞅瞅,一共实现了两种效果,一种是秒动(秒针一秒走一针).另一种是连动式的,秒针不会停会一直走动,话 ...

  2. Android 自定义控件-Canvas和Paint绘图详解-手把手带你绘制一个时钟.

    Android - Paint基础 在自定义控件时,经常需要使用canvas.paint等,在canvas类中,绘画基本都是靠drawXXX()方法来完成的,在这些方法中,很多时候都需要用到paint ...

  3. 用canvas绘制一个圆形,实现绕着一个中心运动

    实现效果 使用canvas绘制一个圆形,实现绕着一个中心,轨迹类似于走一个椭圆的轨迹那样路线,并且实现漂浮的效果. 这里只是一个实例Demo,直接运行就可以,下面附上代码: <!doctype ...

  4. python神奇时钟项目_怎么在Python项目中利用Pygame绘制一个时钟

    怎么在Python项目中利用Pygame绘制一个时钟 发布时间:2020-11-30 14:24:30 来源:亿速云 阅读:54 作者:Leah 怎么在Python项目中利用Pygame绘制一个时钟? ...

  5. html页面画一个矩形,使用HTML5 canvas绘制一个矩形的方法

    使用HTML5 canvas绘制一个矩形的方法 发布时间:2020-08-29 11:23:12 来源:亿速云 阅读:102 作者:小新 这篇文章将为大家详细讲解有关使用HTML5 canvas绘制一 ...

  6. canva五角星空html,使用canvas绘制一个五角星

    一.了解canvas canvas 是HTML5新增的元素,用于在网页上绘制图形.但 canvas 只是图形的容器,必须要通过脚本(通常是JavaScript)来绘制图形. 可以通过多种方法使用can ...

  7. 使用canvas绘制一个动态的表盘

    使用canvas绘制一个动态的表盘 技术要求 需要一点点数学基础 需要对 canvas 的常见的方法熟悉 一点点数学基础 角度转弧度的计算公式 canvas 常见的方法 菜鸟教程 扬帆起航 首先创建一 ...

  8. 使用canvas 绘制一个有限度的斐波那契数列的曲线

    昨天看到"前端面试中的常见的算法问题"的一篇文章,感觉有点挑战,所以才要实现使用canvas 绘制一个有限度的斐波那契数列的曲线,刚开始真是想破脑袋也实现不了,被下图中交接的线条搞 ...

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

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

最新文章

  1. 我国医疗机器人产业发展特征分析
  2. 意法半导体STM32 ARM Cortex 32位微控制器
  3. 通道Channel-IO 多路复用
  4. Redis数据库(四)——Redis集群模式(主从复制、哨兵、Cluster)
  5. rest服务器性能,使用多线程提高REST服务性能
  6. 扒一扒.NET Core的环境配置提供程序
  7. 还有人不知道什么是AndroidX的吗?文末领取面试资料
  8. 对Java注解(Annotation)初步的认识
  9. MyBatis核心接口和类
  10. C++:两个数组求最值、排序、合并
  11. python ttk separator_Python3 tkinter基础 Menu add_cascade 多级菜单 add_separator 分割线
  12. 「leetcode」C++题解:20. 有效的括号,括号匹配是使用栈解决的经典问题
  13. 用SandCastle为注释生成chm文档
  14. SQL 查看SQL语句的执行时间 直接有效的方法
  15. eclipse php使用方法,Eclipse PHPEclipse 配置的具体步骤
  16. 巨量创意signature
  17. 这个是我18年整理的,之前在我的电子笔记,现在感觉还是需要分享写写博客大家互相学习更好
  18. 人脸识别服务器端软件设计(delphi XE10)
  19. LoRA转4G及网关中继器工作原理
  20. dbm数据库源代码分析(3):头文件部分

热门文章

  1. python 模拟按照指定概率进行抽样
  2. 无线WIFI网络系统介绍
  3. 凡人无法打开的文件9
  4. Android 切换全屏,取消全屏
  5. 按需视觉识别:愿景和初步方案
  6. 爬虫快速入门——Request对象的使用
  7. 金蝶EAS客户端批量执行sql代码
  8. 2022 年超过 27 个最流行的计算机视觉应用程序和用例
  9. PAT乙级2021秋季复盘
  10. Python数据可视化之Matplotlib-基础详细篇