Skip to content

时钟启动

本节解释如何使用 HTML Canvas 对我们一直在构建的模拟时钟进行动画处理。

为了让时钟指针移动并实时更新,我们需要以固定的时间间隔重复调用主绘图函数 (drawClock)。setInterval() 方法适用于此任务,特别是对于每秒更新一次的时钟。

以下是如何集成 setInterval():

// 假设 'canvas', 'ctx', 和 'radius' 已经定义并初始化
// 也假设 drawClock(), drawFace(), drawNumbers(), 和 drawTime() 函数已存在。
// const canvas = document.getElementById('myClockCanvas');
// const ctx = canvas.getContext('2d');
// let radius = canvas.height / 2;
// ctx.translate(radius, radius); // 将原点移动到 canvas 中心
// radius = radius * 0.90; // 实际时钟半径
// 协调时钟所有部分的 главная функция рисования
// function drawClock() {
// drawFace(ctx, radius); // 绘制时钟表盘
// drawNumbers(ctx, radius); // 绘制小时刻度
// drawTime(ctx, radius); // 根据当前时间绘制指针
// }
// 不再只调用一次 drawClock():
// drawClock();
// 每 1000 毫秒 (1 秒) 调用一次 drawClock
setInterval(drawClock, 1000);
// --- 完整的概念设置 ---
// (这些函数应该在脚本的其他地方定义)
// function drawFace(ctx, radius) { /* ... 绘制时钟表盘 ... */ }
// function drawNumbers(ctx, radius) { /* ... 绘制刻度 ... */ }
// function drawTime(ctx, radius) { /* ... 获取当前时间并绘制指针 ... */ }
// function setupClock() {
// const canvas = document.getElementById('myClockCanvas');
// const ctx = canvas.getContext('2d');
// let radius = canvas.height / 2;
// ctx.translate(radius, radius);
// radius = radius * 0.90;
// function drawClock() {
// // 清除并重新绘制指针很重要,
// // 但表盘和刻度可能只需要绘制一次,
// // 如果它们不改变的话。为简单起见,这个示例重绘了所有。
// // 更优化的方法是只清除指针所在的区域。
// // 或者,为简单起见,在重绘表盘、刻度和时间之前清除整个时钟区域:
// // ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
// drawFace(ctx, radius);
// drawNumbers(ctx, radius);
// drawTime(ctx, radius);
// }
// setInterval(drawClock, 1000);
// }
// document.addEventListener('DOMContentLoaded', setupClock);

实现时钟动画的核心改变是将一次性的 drawClock(); 调用替换为 setInterval(drawClock, 1000);。

  • setInterval(callbackFunction, delayInMilliseconds): 这个浏览器 API 会每隔 delayInMilliseconds 毫秒重复调用 callbackFunction(在本例中是 drawClock)。
  • 1000: 这个值意味着 drawClock 函数每 1000 毫秒(等于 1 秒)执行一次。这对于模拟时钟(秒针每秒移动)是合适的。
  • 清除 Canvas: 在每次调用 drawClock 时,特别是在绘制移动元素(如指针)之前,通常需要清除上一帧。否则,新的绘图将叠加在旧的绘图之上,产生凌乱的残影。你可以清除整个 canvas:ctx.clearRect(0, 0, canvas.width, canvas.height);,或者如果已经平移了上下文,则使用 ctx.clearRect(-radius, -radius, radius*2, radius*2);。更优化的方法是只清除 canvas 中发生变化的区域(例如,指针所在的区域)。为简单起见,在时钟示例中,通常会重绘整个表盘区域。
  • 性能: 对于复杂的动画,通常推荐使用 requestAnimationFrame() 而非 setInterval()。requestAnimationFrame() 与浏览器的重绘周期同步,可以带来更流畅的动画效果和更好的性能,尤其是在具有不同刷新率的设备上。然而,对于每秒更新一次的简单时钟,setInterval() 已经足够并且对初学者来说更容易理解。
  • 资源管理: 如果时钟从页面中移除或不再需要,你应该使用 clearInterval() 清除定时器,以防止不必要的处理。存储 setInterval() 返回的 ID:const intervalID = setInterval(drawClock, 1000);,然后在需要时调用 clearInterval(intervalID);。

drawClock 函数本身(它调用 drawFace、drawNumbers 和 drawTime)现在将每秒执行一次,确保 drawTime 获取当前时间并将指针绘制到新的位置。