用Canvas实现动态时钟需每秒重绘,核心包括时间计算、极坐标转直角坐标、抗锯齿(ctx.imageSmoothingEnabled = false)及requestAnimationFrame驱动;先设canvas宽高属性(非CSS),获取2D上下文,清空画布,绘制静态表盘与刻度(整点长刻度、其余短刻度,角度从-90°起顺时针),再实时计算时分秒针弧度角度并绘制,注意Y轴向下及时间偏移修正。

用Canvas实现动态时钟,核心是每秒重绘一次表盘和指针,关键在于时间计算、坐标转换(极坐标转直角坐标)、抗锯齿处理和requestAnimationFrame驱动动画。
准备Canvas画布与基础设置
在HTML中声明<canvas>元素,并用JavaScript获取2D渲染上下文。注意显式设置canvas的width和height属性(非CSS样式),否则会拉伸失真。
- 设置
canvas.width = canvas.height = 400等固定像素值 - 用
ctx = canvas.getContext('2d')获取上下文 - 调用
ctx.clearRect(0, 0, canvas.width, canvas.height)清空上一帧 - 启用抗锯齿:
ctx.imageSmoothingEnabled = false(对线条更锐利)
绘制静态表盘与刻度
先画外圆、中心点,再按60个分度(或12小时+60分钟)绘制刻度线。使用ctx.beginPath() + ctx.moveTo()/ctx.lineTo() + ctx.stroke()组合。
- 表盘圆心设为
(cx, cy) = (canvas.width/2, canvas.height/2) - 每5分钟(即12小时制的整点)画长刻度,其余画短刻度
- 角度从顶部(-90°)开始,顺时针旋转:每分钟对应6°,每小时对应30°
- 用
Math.cos(angle) * radius和Math.sin(angle) * radius算出端点坐标
实时计算指针角度并绘制
在动画循环中,用new Date()获取当前时间,分别计算时、分、秒针的角度(单位:弧度),再换算成Canvas坐标系中的终点。
立即学习“前端免费学习笔记(深入)”;
- 秒针:每秒走6° →
secAngle = (seconds * Math.PI / 30) - 分针:每分钟走0.1°(含秒偏移)→
minAngle = ((minutes + seconds/60) * Math.PI / 30) - 时针:每小时走30°,加分钟偏移 →
hrAngle = (((hours % 12) + minutes/60) * Math.PI / 6) - 所有指针起点均为
(cx, cy),终点用三角函数+长度确定 - 建议给秒针加一点透明度(
ctx.globalAlpha = 0.8)增强动感
驱动平滑动画循环
不用setInterval,改用requestAnimationFrame保证60fps且节电。每次回调中更新时间、清除画布、重绘全部内容。
- 定义主绘制函数
drawClock(),内部调用自身递归 - 用
requestAnimationFrame(drawClock)启动循环 - 可选:添加
ctx.save()和ctx.restore()隔离变换状态 - 如需暂停,用
cancelAnimationFrame(id)取消上一次请求
不复杂但容易忽略细节:角度起始方向、坐标系Y轴向下、时间偏移修正、canvas像素比适配高DPI屏幕(可通过window.devicePixelRatio调整)。实现后,你得到的是一个轻量、可定制、完全运行在前端的SVG级精度时钟。



















