0

0

JavaScript 计时器精准实现与动态格式化输出教程

霞舞

霞舞

发布时间:2026-03-07 13:42:12

|

498人浏览过

|

来源于php中文网

原创

本文介绍如何基于 setInterval 构建高精度、可读性强的计时器,并实现智能时间格式化:自动省略前导零、按需显示小时/分钟,且毫秒部分精确到三位(如 1.230 → 1.23 仅需简单截断,但推荐保留三位以保障精度与一致性)。

本文介绍如何基于 `setinterval` 构建高精度、可读性强的计时器,并实现智能时间格式化:自动省略前导零、按需显示小时/分钟,且毫秒部分精确到三位(如 `1.230` → `1.23` 仅需简单截断,但推荐保留三位以保障精度与一致性)。

在开发魔方计时器(cubing timer)等对时间敏感的应用时,单纯依赖 setInterval + 手动累加毫秒数(如 milliseconds += 10)存在本质缺陷

  • setInterval 无法保证严格准时执行(受事件循环、JS 单线程阻塞、浏览器节流等影响);
  • 函数执行耗时会累积误差,长时间运行后偏差可达数百毫秒;
  • 手动进位逻辑易出错(如原代码中 seconds == 60 后误写为 seconds = 60,导致卡死)。

✅ 正确做法是:以时间戳为基准,实时计算经过的总毫秒数,再统一换算为时分秒毫秒。这既保证精度,又简化逻辑。

✅ 推荐实现:高精度时间戳驱动 + 动态格式化

以下为优化后的完整代码(含注释),已解决您提出的两大核心问题:

AskAI
AskAI

无代码AI模型构建器,可以快速微调GPT-3模型,创建聊天机器人

下载
  • 格式精简:00.000 → 0.000(去前导零),01.230 → 1.230;
  • 按需显示单位:仅当 hours > 0 时显示 X h;仅当 minutes > 0 时显示 MM:;秒与毫秒恒定显示为 SS.MMM 格式(padStart(2, "0") 和 padStart(3, "0") 保障对齐,视觉清晰)。
// --- 核心计时器逻辑 ---
let startTime = 0;
let timeRef = document.querySelector("#timer");
let int = null;

function startTimer() {
  if (int !== null) clearInterval(int);
  int = setInterval(displayTimer, 10); // 每10ms刷新一次(足够平滑)
  startTime = Date.now(); // 使用更现代、性能更好的 Date.now()
}

function stopTimer() {
  clearInterval(int);
  int = null;
}

function resetTimer() {
  stopTimer();
  timeRef.textContent = "0.000";
  startTime = 0;
}

// 辅助函数:整除与取余(避免重复 Math.floor + %)
function divmod(a, b) {
  return [Math.floor(a / b), a % b];
}

function displayTimer() {
  const totalMs = Math.round(Date.now() - startTime); // 总毫秒数(四舍五入消除浮点误差)
  const [totalS, ms] = divmod(totalMs, 1000);         // 秒数 & 毫秒余数
  const [totalM, s] = divmod(totalS, 60);            // 分钟数 & 秒余数
  const [h, m] = divmod(totalM, 60);                 // 小时数 & 分余数

  // ✨ 动态构建显示字符串:按需添加单位,无冗余前导零
  let formatted = "";
  if (h > 0) formatted += `${h} h `;                    // 例:`1 h `
  if (m > 0) formatted += `${String(m).padStart(2, "0")}:`; // 例:`01:`
  formatted += `${s}.${String(ms).padStart(3, "0")}`;   // 恒定显示 SS.MMM,如 `59.990`

  timeRef.textContent = formatted;
}

// --- 键盘控制(简化版:空格键启停)---
document.addEventListener('keydown', (e) => {
  if (e.code === 'Space' && !e.repeat) {
    if (int) {
      stopTimer();
    } else {
      startTimer();
    }
  }
});

// --- 初始化显示 ---
timeRef.textContent = "0.000";

⚠️ 关键注意事项

  • 毫秒显示建议保留三位:虽然您希望显示 1.23,但魔方竞速规则要求精确到 0.001 秒(WCA 规则),且 0.000 → 0.00 会丢失精度感知。若坚持两位小数,可将 String(ms).padStart(3, "0") 替换为 String(Math.round(ms / 10))(即四舍五入到厘秒),但不推荐。
  • textContent 优于 innerHTML:避免 XSS 风险,且纯文本更新更快。
  • Date.now() 优于 +new Date():更简洁、性能略优。
  • 状态管理解耦:原代码中复杂的 state 机可被简化——计时器启停本质是二元操作(运行中→停止,停止→启动),无需过度设计。

✅ 最终效果示例

经过时间 显示结果 说明
0.990s 0.990 无前导零,毫秒三位对齐
59.990s 59.990 秒数无补零
60.000s 1:00.000 自动进位到分钟,显示 MM:SS.MMM
3661.123s 1 h 1:01.123 小时+分钟+秒毫秒全量显示

通过此方案,您将获得一个高精度、易维护、符合赛事规范的计时器核心,同时完全满足格式动态化需求。后续如需添加暂停/分段时间、统计功能,均可在此健壮基础上扩展。

立即学习Java免费学习笔记(深入)”;

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

970

2023.08.02

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

743

2023.08.10

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

554

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

718

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

6024

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

492

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.09.04

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

1

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5.8万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号