翼度科技»论坛 编程开发 html5 查看内容

记录--canvas 复刻锤子时钟

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助



介绍

canvas:使用脚本 (通常为 JavaScript) 来绘制图形的 HTML 元素。
本人遍历了以下两份文档,学习完就相当于有了笔和纸,至于最后能画出什么,则需要在 canvas 应用方面进一步学习。

  • MDN 的 Canvas 教程1
  • 张鑫旭的 Canvas API 中文文档2
Demo 时钟

下面介绍如何使用 canvas 制作一个时钟,首先分析一个简单的时钟包含哪些部分:

  • 表盘
  • 时针 / 分针 / 秒针
  • 按秒走时
初始化 canvas 画布
  1. <canvas id="clock"></canvas>
  2. /* css */
  3. canvas {
  4.   width: 300px;
  5.   height: 300px;
  6. }
  7. // js
  8. const radio = window.devicePixelRatio;
  9. const width = 300 * radio;
  10. const height = 300 * radio;
  11. const canvas = document.getElementById('clock');
  12. const ctx = canvas.getContext('2d');
  13. canvas.width = width;
  14. canvas.height = height;
复制代码
ctx 对应 “Canvas 2D 渲染上下文”,暴露了大量 API 属性和方法,用于绘制形状,文本,图像和其他对象。
devicePixelRatio 是当前显示设备物理像素分辨率与 CSS 像素分辨率之比。假设该值为 2,表示浏览器使用 2 个物理像素来绘制 1 个 CSS 像素。在上面代码中,会将 canvas 画布尺寸按照该值放大,使图像更清晰。
绘制表盘
  1. /**
  2. * 绘制表盘
  3. */
  4. const drawCircle = () => {
  5.   ctx.save();
  6.   ctx.translate(width / 2, height / 2);
  7.   ctx.fillStyle = '#f8f9fa';
  8.   ctx.beginPath();
  9.   ctx.arc(0, 0, 0.4 * width, 0, 2 * Math.PI);
  10.   ctx.fill();
  11.   ctx.restore();
  12. }
复制代码
save() 和 restore() 可以看作是一对方法,前者保存当前 canvas 画布状态并放在栈最上面,后者将状态依次取出。以 fillStyle 属性为例,代码中 restore 方法执行后,fillStyle 将恢复为之前设置的值。
translate() 对 canvas 坐标系进行整体位移,这里用于变换中心点。
beginPath() 开始一个新路径,之后由 arc() 绘制一个整圆,路径本身没有颜色,可以通过描边或填充为路径着色,代码中使用 fill() 方法为整圆填充颜色,作为表盘。
绘制指针
  1. /**
  2. * 绘制单根指针
  3. * @param {Number} deg 指针沿 12 点钟方向顺时针旋转角度
  4. * @param {Number} l 指针长度(比例值)
  5. * @param {String} rgb 指针颜色
  6. */
  7. const pointer = (deg, l, rgb) => {
  8.   ctx.save();
  9.   ctx.rotate(deg);
  10.   ctx.lineWidth = radio;
  11.   ctx.strokeStyle = rgb;
  12.   ctx.beginPath();
  13.   ctx.moveTo(0, 0);
  14.   ctx.lineTo(0, 0 - l * width);
  15.   ctx.stroke();
  16.   ctx.restore();
  17. }
  18. /**
  19. * 计算时针、分针、秒针的角度并调用 pointer 函数绘制
  20. */
  21. const drawPointer = () => {
  22.   const date = new Date();
  23.   const h = date.getHours() % 12;
  24.   const m = date.getMinutes();
  25.   const s = date.getSeconds();
  26.   const h_deg = ((m / 60 + h) / 12) * 2 * Math.PI;
  27.   const m_deg = ((s / 60 + m) / 60) * 2 * Math.PI;
  28.   const s_deg = (s / 60) * 2 * Math.PI;
  29.   ctx.save();
  30.   ctx.translate(width / 2, height / 2);
  31.   pointer(h_deg, 0.2, '#4e4e4e');   // 时针
  32.   pointer(m_deg, 0.25, '#4e4e4e');  // 分针
  33.   pointer(s_deg, 0.35, '#c32927');  // 秒针
  34.   ctx.restore();
  35. }
复制代码
单根指针是由一条指向 12 点钟方向的直线,沿着表盘中心点顺时针旋转指定角度后构成。drawPointer 函数计算出三根指针各自与 12 点钟方向的夹角,再调用 pointer 函数一一绘制。
pointer 函数中,rotate() 方法将画布沿着变换后的中心点顺时针旋转指定角度,moveTo()、lineTo() 方法再绘制一条从中心点指向原 12 点钟方向的路径,使用 stroke() 为路径添加描边,如此便完成了一根对应当前时间的指针。
按秒走时
  1. setInterval(() => {
  2.   ctx.clearRect(0, 0, width, height);
  3.   drawCircle();
  4.   drawPointer();
  5. }, 1000);
复制代码
每隔 1 秒钟擦除一次画布,然后重新绘制表盘与指针即可。
效果
上面代码合起来运行,就能得到一个如下图所示的简单时钟:

Smartisan 时钟

曾经有一部心爱的 锤子(Smartisan)坚果 R1 手机,后来……总之手机自带的 锤子时钟 我很喜欢,而时间来到 2023 年时,Android 版只剩魅族应用市场在架,版本停留在了 1.4.1,IOS 在 2016-03-25 更新了最后一个版本 1.4.2 后,在 2021-04-14 便一直下架了。
好在我的 iPhone 手机之前下载过,在已购项目中重新下载,打开应用截个图:

 在上面代码中,只是实现了一个最简单的 demo 版时钟,现在加一点点细节,复刻一下锤子时钟,效果如下:


代码放在了 codepen,有兴趣的话请移步。
本文转载于:

https://juejin.cn/post/7262280335979085861

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 


来源:https://www.cnblogs.com/smileZAZ/p/17601319.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具