键盘上哪个键失灵,很多人是打到一半才发现。
我做了个网页:按下任意键,键盘图上对应的位置立刻点亮,松开就灭。
顺手把三件事也量了出来:同时按几个键能被识别、长按的重复间隔是多少、一次按键从事件到渲染用了多少毫秒。

它只做四件事:点亮、统计、计时、热力图。
不做按键寿命测试,也判断不了是硬件坏还是驱动坏。
先给三条硬信息。
- 公开位置:Demo Park 仓库的
codearts-keyboard-test目录,源码、文档、截图都在里面。 - 运行方式:把
index.html下载到本地双击就能用,零依赖,不联网。 - 实测数字:42 次真实按键,延迟平均 21.2 ms、最大 40.5 ms、最小 1.2 ms。
仓库没附单独的许可文件,代码随案例目录公开取用。
一、为什么值得做这个检测
键盘故障是渐进的,不像硬盘那样一次性报废。
一开始只是某个键要按重一点,后来偶尔丢一次,再后来彻底不响应。
网上搜「键盘测试」,结果基本分两类。
一类是装机城的广告页,点进去先让你挑键盘型号;另一类只有一片灰色键位图,能点亮,但没有延迟、没有连发、没有热力图。
我想要的是一页把「有没有坏、坏在哪、响应有多快」都摊开。
选这个题还有个很实际的理由:搜索词足够实在。
「键盘测试」「按键检测」「键盘无冲」每天都有人搜,而且搜的人不需要任何前置知识。
谁都有键盘,谁都想确认自己那把还灵不灵。
二、进入码道 Web 与准备环境
码道有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。这篇用 WebUI 版演示。
浏览器打开码道 Web 版:devcloud.cn-north-4.huaweicloud.com/chat?source…,登录后在对话框里直接写需求,不用装任何软件。
我给的需求拆成七条:全尺寸键盘布局、实时统计卡片、同时按键测试、响应延迟测量、长按连发测试、键位热力图、重置按钮。
产出是一个纯前端单文件 index.html,深色界面,双击就能跑。
页面里的键盘用 101 个键位拼出来,实时点亮的键盘和底部的热力图各一套,加起来 202 个键位元素。
三、页面上有哪四块
设计拆开看,四块各管一件事。
| 区域 | 位置 | 判据 |
|---|---|---|
| 全尺寸键盘布局 | 顶部主区 | 按 keydown 点亮,keyup 熄灭;左右 Shift / Ctrl / Alt / Win 分成 8 个独立键位 |
| 实时统计 | 顶部 5 张卡片 | 当前按下键数、不同键数、总按键次数、最大同时按键数、当前同时识别 |
| 三块检测面板 | 中部 | 响应延迟(本次 / 平均 / 最大 / 最小 + 20 根条形图)、长按连发(次数 / 平均间隔 / 首次重复延迟)、无冲(同时识别 / 历史最大 / 当前按下的键) |
| 键位热力图 | 底部 | 每个键被按过的次数,颜色越亮次数越多,鼠标悬停显示数字 |
键位用的是 KeyboardEvent.code,不是 key。
这个选择是对的:code 按物理位置走,切到别的键盘布局、按住 Shift 敲数字,键位也不会跳。
左右修饰键因此能分开统计,L-Shift 和 R-Shift 是两格亮度,不是一格。
四、实测数字:42 次真实按键
数据是这台机器上跑出来的,不是估的。
我一共送了 42 次真实按键,覆盖 32 个不同键位,热力图上按得最多的是 E,5 次。
| 指标 | 数值 |
|---|---|
| 真实按键次数 / 不同键位 | 42 次 / 32 个 |
| 延迟平均 / 最大 / 最小 | 21.2 ms / 40.5 ms / 1.2 ms |
| 同一窗口的帧间隔平均 / 最大 / 最小 | 17.61 ms(29 帧)/ 47.3 ms / 9.5 ms |
| 同时按下 6 键(A S D J K L) | 当前识别 6 键,历史最大 6 键 |
| 长按 H 的重复次数 / 平均间隔 | 14 次 / 75.4 ms(首次重复延迟 603.8 ms) |
| 单页键位元素 | 101 × 2 = 202 个 |
| 无布局键 AudioVolumeUp 按下 | 统计 +1,点亮的键 0 个 |
延迟那一行的数字要和帧间隔那一行一起看,第五节说原因。
同时按键这一项,我按住 A S D J K L 六个键不放,页面右侧的「同时识别」停在 6,历史最大也是 6。

截图里的六个键同时亮着,正下方的「当前按下的键」把它们按顺序列了出来。

长按那一项,H 键在按住期间触发了 14 次重复,页面算出的平均间隔是 75.4 ms。

五、我在现场:几个失败路径与边界
第一处是卡键告警,这是页面唯一会变红的提示。
我给页面送了一次只有按下、没有抬起的按键事件,再把窗口失焦事件触发一遍,告警条立刻亮起,原文是:
⚠ 按键按下后没有收到抬起事件:X(可能焦点丢失或按键卡住)

这个提示在真实场景里也不是空设:按住某个键的时候切走窗口、或者系统吞掉了 keyup,都会落到这条路径上。
第二处边界更隐蔽:统计卡片会自相矛盾。
失焦时页面把「当前按下键数」清零,同时又把这些键记进告警名单。
所以截图 05 里左侧卡片写着 0,右边红字写着 X。
第三处是键盘图上没有的键。
我送了一个多媒体键 AudioVolumeUp,统计卡片「当前按下键数」变成 1、「不同键数」也是 1,但两张键盘上一个格都没亮。
布局是按标准 104 键画的,多媒体键、日语键盘的多余键位都落在图外。
第四处是长按会污染延迟面板。
延迟面板的口径是「最近 20 次按键」,而页面在每次 keydown 时都记一次样本,包括系统自动重复的那些。
长按 H 的时候,页面收到 1 次真实按下加 14 次重复,面板的 20 格里就被 15 个样本填满,条形图上能一根一根数出来。
想量真实的手速或者键与键的间隔,得先点右上角的重置。
第五处是 F 键与 Tab、空格这些键被页面吃掉了默认行为。
代码里有一份 preventCodes 名单,命中就 preventDefault(),按 F5 不会刷新页面,按 Tab 不会跳焦点,按空格不会滚屏。
这是为了检测不打断操作,代价是这些键在这页上不能当正常按键用。
六、验证与踩坑
本地跑起来只要一条命令:
python -m http.server 8080
然后打开 http://127.0.0.1:8080/index.html。双击 index.html 直接进浏览器也一样,页面不依赖服务器。
按键数据是我用 Chrome 的 DevTools 协议送进页面的。
这样发出来的事件 isTrusted 是 true,和真人敲键盘走的是同一条路,我在页面里挂了一个探针确认过:
[{"code":"KeyA","trusted":true,"key":"a"}]
这一轮我做了 7 项测试:42 次单键延迟、29 帧的帧间隔、6 键同按、长按连发、卡键告警、无布局键、左右修饰键区分。
七项都跑完了,数字都在上一节。
最大的坑是延迟的口径,值得单独说。
页面里的「响应延迟」公式是 渲染帧时间 - 事件 timeStamp。
它在 keydown 里挂一个 requestAnimationFrame,等下一帧渲染时用 performance.now() 减去事件时间戳:
requestAnimationFrame(() => {
const renderTime = performance.now();
let latency = renderTime - event.timeStamp;
if (latency < 0) latency = 0;
});
所以这个数字量的不是键盘硬件到系统的延迟,而是「事件发生到这一帧画出来」。
我同时量了 29 帧的间隔做对照:平均 17.61 ms、最大 47.3 ms。
按键延迟的平均 21.2 ms、最大 40.5 ms 和它基本同量级,最大那一次就是碰上了一个慢帧。
换句话说,这台机器上按键延迟的分布由浏览器帧率决定,不是由键帽下的弹簧决定。
要测真正的硬件延迟,得换成 keydown 到 keyup 的回环、或者上示波器,一个网页量不了。
第二个坑是长按连发那一项在脚本里量不出真实倍率。
页面的平均间隔算的是相邻两次重复事件的时间差,公式没问题。
我用脚本按固定节奏补出重复事件,页面报回 75.4 ms,正好是这些事件实际落地的间隔,不是我在脚本里写的那个值。
这说明它确实在量真实时间戳,而不是回显参数。
第三个坑是首次重复延迟。
页面显示 H 键的首次重复延迟是 603.8 ms,这个数字由我这边的等待时长决定,不是键盘的重复延迟设置。
想量自己系统的重复延迟,得真的用手指按住不放。
七、使用码道的体会
先说结果:一份七条要点的需求,拿到的是一个能直接跑的整页应用,四块检测、横竖两套键盘图、深色主题都在里面。
细节是它自己补的,而且补在了我看不到的地方。
比如 preventCodes 那份名单、切窗失焦时把按住的键标成卡住、键盘图随窗口宽度自适应缩放。
这几处我在写需求时都没想到,是看了代码才发现它做了。
它自己还写了个校验脚本,在页面里按下 A S D 三个键,读回点亮状态和统计卡片的值,确认逻辑对得上。
这部分我没插手,读代码时看到它在自测。
不满意的也有一处:延迟口径从一开始就是 rAF 差值,也就是「到下一帧」的时间。
这个口径在页面上写得很清楚,footer 里就写着 延迟 = 渲染帧时间 (rAF) − 事件 timeStamp。
它没骗人,但这个词容易被读者当成硬件延迟。
我在文章里把口径和帧间隔数据一起摆出来,就是不想让这个数字被误读。
八、直接下载试玩
这个 Demo 的源码、本文档和 5 张截图都在公开仓库里:
- Demo Park 仓库:atomgit.com/deli007/dem…
- 本案例目录:atomgit.com/deli007/dem…
进目录把 index.html 下载到本地,双击打开就能测自己那把键盘。
九、小结
一页纸能做出来的键盘检测,比想象中多。
42 次真实按键里,平均延迟 21.2 ms、最慢的一帧 40.5 ms,而同一时刻的浏览器帧间隔平均就是 17.61 ms。
所以这个页面能回答「哪个键不响应、同时按几个键能被识别、长按有没有重复」,不能回答「这把键盘的硬件延迟是多少」。
下一步想加的是按键回环计时:把 keydown 到 keyup 的间隔也记下来,两套数字并排摆,读者自己就能看出哪部分是浏览器、哪部分是硬件。
那是另一轮的事了。