Canvas时钟核心是将时间转为弧度,用cos/sin计算指针端点坐标:秒针每秒π/30、分针π/1800、时针π/21600弧度,并叠加秒偏移;坐标公式为x=cx+len×sin(rad)、y=cy−len×cos(rad);用requestAnimationFrame实现平滑更新。

Canvas 时钟的核心是把时间转换成角度,再用三角函数算出指针端点坐标,最后用 lineTo 或 arc 绘制。
时间到弧度的映射关系
秒、分、时三针每秒/每分钟转动的角度不同,需统一换算为弧度(Canvas 的 rotate 和三角函数都用弧度):
- 秒针:60 秒转一圈 → 每秒转 2π / 60 = π / 30 ≈ 0.1047 弧度
- 分针:60 分钟转一圈 → 每秒转 2π / (60 × 60) = π / 1800 ≈ 0.001745 弧度
- 时针:12 小时转一圈 → 每秒转 2π / (12 × 3600) = π / 21600 ≈ 0.000145 弧度
注意:分针和时针要叠加“当前秒数带来的偏移”,例如 2:30:45 的时针不能只按 2.5 小时算,得是 2 + 30/60 + 45/3600 = 2.5125 小时,再乘以 π/21600 才准确。
用 cos/sin 计算指针终点坐标
Canvas 坐标原点默认在左上角,而钟表中心通常设在画布中央。设中心为 (cx, cy),指针长度为 len,旋转角度为 rad(从正右方向逆时针起算),则终点为:
立即学习“前端免费学习笔记(深入)”;
- x = cx + len × cos(rad)
- y = cy − len × sin(rad)(注意减号:Canvas 的 y 轴向下为正)
但默认 0 弧度指向右,而钟表 12 点方向应为 0 角度,所以需整体顺时针偏移 π/2,即实际使用角度为 rad − π/2;代入后可简化为:
- x = cx + len × sin(rad)
- y = cy − len × cos(rad)
动态更新与 requestAnimationFrame
不推荐用 setInterval 每秒 redraw,因 Canvas 渲染耗时可能造成跳秒或卡顿。应使用 requestAnimationFrame 驱动循环,并在每次绘制前读取实时时间:
- 获取
new Date(),提取getHours()、getMinutes()、getSeconds()、getMilliseconds() - 将毫秒级精度融入计算(如秒针位置 =
s + ms / 1000),实现平滑转动 - 每次先
clearRect清空画布,再重绘背景圆、刻度、三根指针(建议从小时→分钟→秒顺序绘制,避免遮挡)
视觉细节的关键数学处理
真实时钟有渐变、阴影、指针粗细差异等,这些虽非核心逻辑,但依赖精确坐标:
- 刻度线:12 小时刻度每 30°(π/6 弧度)一个,可用
for (let i = 0; i 循环生成端点 - 数字标注:用
fillText时,需根据角度调整文字锚点(textAlign和textBaseline),并用相同 sin/cos 算出定位偏移 - 指针中心小圆:半径固定,但建议用
arc(cx, cy, r, 0, Math.PI * 2)填充,增强机械感
所有角度运算必须基于同一时间戳,否则秒针、分针、时针会因多次 new Date() 微小差异而短暂错位。











