【html】canvas实现一个时钟

前言

"一行代码能做什么?"------有人用一行代码写出圣诞树,有人用一行代码写出 3D 隧道。

今天我想带你回到最原始的画布:HTML5 Canvas。

我们只用 一个 <canvas> 标签 + 一份被注释到"膨胀"的源码 ,做一只实时跳动的机械时钟

读完你不仅能照抄代码,还能彻底搞懂:

  1. 为什么 requestAnimationFramesetInterval 更适合动画
  2. 三角函数在前端到底怎么用
  3. 如何把"时间"映射成"角度"再映射成"坐标"

在线预览

把下面 60 行"真身"粘进任意 .html 文件,双击即可运行:

(我已经把注释写成了"伪 600 行"------每行都带中文讲解,复制即食)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>Canvas Clock | 注释版</title>
  <style>
    /* 让时钟水平居中,再给个浅灰背景+深色边框,高级感拉满 */
    canvas {
      display: block;
      margin: 50px auto;
      background: #f4f4f4;
      border: 2px solid #333;
      border-radius: 50%; /* 圆表盘当然要圆角 */
      box-shadow: 0 0 20px rgba(0,0,0,.15);
    }
  </style>
</head>
<body>
  <!-- 600×600 像素的画布,id 叫"clock",后面 JS 就靠它画画 -->
  <canvas id="clock" width="600" height="600"></canvas>

  <script>
    /* 主绘制函数:每帧擦掉旧画面 -> 重新画新画面,形成动画 */
    function drawClock() {
      const canvas = document.getElementById('clock');
      const ctx    = canvas.getContext('2d');      // 拿到 2D 画笔
      const cx = 300, cy = 300, r = 250;           // 圆心(cx,cy) 半径 r

      /* 1. 清屏:把上一帧的画面整个擦掉,避免拖影 */
      ctx.clearRect(0, 0, 600, 600);

      /* 2. 表盘:一个灰色大圆 */
      ctx.beginPath();
      ctx.arc(cx, cy, r, 0, Math.PI * 2);
      ctx.fillStyle = '#ccc';
      ctx.fill();

      /* 3. 拿到当前时分秒 */
      const now = new Date();
      const h = now.getHours();
      const m = now.getMinutes();
      const s = now.getSeconds();

      /* 4. 角度换算:把"时间"转成"顺时针角度",再减去 90° 让 0° 指向 12 点 */
      const hAngle = ((h % 12) + m / 60) * 30  - 90;  // 每小时 30°
      const mAngle = (m + s / 60)        * 6   - 90;  // 每分钟 6°
      const sAngle = s                   * 6   - 90;  // 每秒 6°

      /* 5. 画三根指针:颜色、长度、线宽各不相同,秒针用骚红色 */
      drawHand(ctx, hAngle, 100, 12, '#333');         // 时针
      drawHand(ctx, mAngle, 150, 8,  '#555');         // 分针
      drawHand(ctx, sAngle, 180, 3,  '#e74c3c');      // 秒针

      /* 6. 中心小圆点:盖住三根指针的尾巴,显得更像实物 */
      ctx.beginPath();
      ctx.arc(cx, cy, 10, 0, Math.PI * 2);
      ctx.fillStyle = '#333';
      ctx.fill();

      /* 7. 请求下一帧:浏览器会在下一次重绘前再调 drawClock(),形成无限循环 */
      requestAnimationFrame(drawClock);
    }

    /* 工具函数:画一根指针
       angle:旋转角度(度)  length:长度   width:线宽   color:颜色 */
    function drawHand(ctx, angle, length, width, color) {
      const rad = (angle * Math.PI) / 180;   // 角度转弧度
      const x = 300 + Math.cos(rad) * length;
      const y = 300 + Math.sin(rad) * length;

      ctx.beginPath();
      ctx.moveTo(300, 300);
      ctx.lineTo(x, y);
      ctx.lineWidth = width;
      ctx.strokeStyle = color;
      ctx.lineCap = 'round';   // 圆角线帽,更柔和
      ctx.stroke();
    }

    /* 启动!第一次手动调用,后面就靠 requestAnimationFrame 自动循环 */
    drawClock();
  </script>
</body>
</html>

关键知识点拆解

步骤 前端技巧 一句话记忆
清屏 ctx.clearRect 动画第一定律:先擦后画
角度 -90° 修正 数学 0° 指向 3 点,时钟 0° 指向 12 点
弧度 Math.PI / 180 角度给人类看,弧度给三角函数看
指针终点 cos 管 x,sin 管 y 高中三角函数终于还给了体育老师
动画节流 requestAnimationFrame 浏览器帮你匹配屏幕刷新率,60 fps 不丢帧

还能怎么玩?

  1. 换皮肤:把表盘改成深色霓虹,秒针加 glow 阴影,瞬间赛博朋克。
  2. 加刻度 :用 for 循环画 60 个小圆点,12 个粗点代表小时。
  3. 加数字ctx.fillText 把 1~12 画到对应位置,注意同样要转角度。
  4. 响应式 :把 600 改成 min(window.innerWidth, window.innerHeight),再动态算圆心。
  5. 音效:每秒播放一次"滴答"采样,Web Audio API 只要 5 行。

结语

Canvas 像一张永远干不掉的水彩纸:

你可以在上面画像素、画粒子、画星空,也可以画一只最朴素的时钟。
"会动"的不只是指针,还有你对前端世界的好奇心。

把这份代码存进收藏夹,下次面试被问到"如何实现平滑动画"时,

requestAnimationFrame + 三角函数 这套组合拳打出来,

面试官大概率会点点头:嗯,基础很扎实。


源码仓库

GitHub 完整仓库

👉 gitter.com/koreation/canvas-clock 欢迎 Star & PR!


如果这篇文章帮到你,记得点个赞,
让你的时间,也像 Canvas 里的秒针一样,优雅前行。

相关推荐
卓码软件测评2 小时前
第三方软件登记测试机构:【软件登记测试机构HTML5测试技术】
前端·功能测试·测试工具·html·测试用例·html5
阿昭L2 小时前
html快速学习
html
qianmo20212 小时前
基于any2web+deepseek实现对三角函数定义的理解
css·html·css3
林烈涛2 小时前
js判断变量是数组还是对象
开发语言·前端·javascript
Komorebi_99993 小时前
Unocss
开发语言·前端
goto_w4 小时前
前端实现复杂的Excel导出
前端·excel
Baklib梅梅4 小时前
2025文档管理软件推荐:效率、安全与协作全解析
前端·ruby on rails·前端框架·ruby
卷Java4 小时前
小程序前端功能更新说明
java·前端·spring boot·微信小程序·小程序·uni-app
FogLetter4 小时前
前端性能救星:虚拟列表原理与实现,让你的10万条数据流畅如丝!
前端·性能优化