最简单的方法就是打开一个反应测试:等屏幕发生变化,然后尽快点击,最后得到一个以毫秒为单位的数字。
例如:
203 ms
看起来非常直观。
但自己真正连续测几十次以后,我越来越觉得,真正有意思的问题并不是“怎么把这 203ms 算出来”,而是:
203ms 到底意味着什么?
我最开始做反应力测试的时候,也只是想把一个很简单的流程做出来。后来越测越多,才发现一个看起来只有“等一下,再点一下”的页面,里面其实藏着不少问题。
最基本的反应测试是怎么工作的?
最常见的视觉反应测试流程非常简单。
页面先进入等待状态,经过一段随机时间以后显示信号,用户看到信号以后尽快操作,然后计算两者之间的时间差。
用 JavaScript 表达,大概可以简化成这样:
let signalTime = 0;
function showSignal() {
signalTime = performance.now();
showGreenScreen();
}
function handleReaction() {
const reactionTime = performance.now() - signalTime;
showResult(Math.round(reactionTime));
}
所以从纯粹的计时逻辑来说,反应速度测试并不复杂。
真正开始让用户反复测试以后,需要处理的东西会多很多。
例如用户还没看到信号就提前点了怎么办?一次测试结束以后什么时候进入下一轮?鼠标、键盘和触屏是不是应该共用同一套状态?测试进行到一半离开页面又应该怎么办?
我后来更愿意把它当成一个小状态机:
READY
↓
WAITING
├── 提前操作 → TOO SOON
↓
SIGNAL
↓
REACTION
↓
RESULT
计时只有几行代码,但一个反应测试玩起来是否自然,往往取决于这些细节。
为什么每次测出来都不一样?
这是我自己反复测试以后最先注意到的问题。
同一个人连续测试几次,很可能得到这样的结果:
203 ms
218 ms
194 ms
211 ms
206 ms
它很少会稳定在一个完全固定的数字上。
这其实很好理解。人在每一次测试里的注意状态、预期程度和操作都不会完全一样,而且浏览器最终记录到的成绩还包含设备和输入过程带来的影响。
所以一次特别快的成绩,并不一定代表平时的正常水平;偶尔一次明显变慢,也没必要马上理解成自己的反应突然下降了。
这也是为什么我后来没有只保留“最好成绩”。
如果五轮分别是:
203 / 218 / 194 / 211 / 206
只告诉用户:
Best: 194 ms
其实丢掉了不少信息。
如果同时看到:
Best: 194 ms
Average: 206.4 ms
对这几轮测试的理解会完整很多。
我后来更喜欢看平均值,而不是最好的一次
最好成绩当然很有吸引力。
因为看到一个比以前更小的数字,很容易让人产生:
再来一次,说不定还能更快。
但如果想了解自己当前大概处在什么状态,我现在更愿意看多轮结果。
所以现在这个反应时间测试同时保留了单轮和五轮两种方式。
单轮适合随手测一下。
五轮则更适合观察:
- 最快成绩
- 平均成绩
- 每一轮之间的波动
- 最近几次和以前有什么不同
对我来说,这比只追求一次极限成绩更有意思。
反应测试、反应速度测试、反应力测试,其实在说什么?
中文里这几个词经常混在一起使用。
有人会搜索“反应测试”,有人习惯说“反应速度测试”,也有人会说“反应力测试”或者“反应时间测试”。
在这种浏览器小游戏里,它们通常都指向一个类似的问题:
从视觉信号出现,到用户完成响应,中间经过了多少时间?
所以真正直接得到的是一个 reaction time(反应时间)。
“反应速度”和“反应力”更像日常表达。
我做中文页面的时候,没有特别想强行规定只有某一种说法才是正确的,因为真实用户本来就会用不同的词来表达同一个需求。
比词本身更重要的是,让用户知道这个数字是怎么来的,以及它有什么限制。
200ms 和 210ms,真的能直接比较吗?
不一定。
这是浏览器反应测试特别需要注意的一点。
一个最终显示出来的时间,并不是完全脱离设备的“人体反应数字”。
整个过程更接近:
信号应该出现
↓
显示设备真正显示出来
↓
眼睛看到
↓
大脑作出反应
↓
手完成操作
↓
鼠标 / 键盘 / 触屏产生输入
↓
系统和浏览器收到事件
页面最后记录的是这整条链路中的结果。
所以换一台显示器、换成手机触屏,或者从鼠标改成键盘以后,成绩出现变化并不奇怪。
因此如果一台电脑测出 195ms,手机测出 215ms,我不会简单得出:
“我在电脑上的人体反应快了 20ms。”
这两个数字里面还混有不同设备环境带来的差异。
所以我现在更推荐和自己比较
如果只是把反应测试当成小游戏,当然不用想这么多。
但如果真的想观察自己的变化,一个很实用的方法是:
尽量固定设备和操作方式。
比如一直使用同一台电脑、同一个浏览器、同一个鼠标,然后每次都完成五轮测试。
这样至少减少了一部分额外变量。
今天:
Average: 212 ms
过几天:
Average: 203 ms
这种比较通常比:
我的手机 218ms
别人电脑 190ms
更有意义。
也正因为这样,我开始保存最近成绩
最早的页面其实只有:
203 ms
Try Again
然后结束。
自己玩了一段时间以后,我发现这种页面有个很明显的问题。
隔几天再回来,已经完全记不住上一次是多少了。
于是后来开始把最近成绩和最好成绩留在浏览器里。
没有账号,也没有为了这么一点数据去做复杂的服务器同步,只是用 localStorage 保存最近记录。
例如:
const key = 'reaction-history';
function saveReactionTime(score) {
const history = JSON.parse(
localStorage.getItem(key) || '[]'
);
history.unshift({
score,
time: Date.now()
});
localStorage.setItem(
key,
JSON.stringify(history.slice(0, 20))
);
}
从技术上来说这没什么特别。
但产品体验却从:
测试 → 得到一个数字
慢慢变成:
测试 → 成绩 → 历史 → 比较 → 再测试
我现在觉得,后面这几个步骤其实比单纯把计时精确到更多小数位重要得多。
怎样让一次反应测试更有参考价值?
我自己现在会注意几个很简单的事情。
第一,不要只测试一次。
一次特别好或者特别差的结果都可能有偶然性,多轮测试更容易看到正常波动。
第二,不要为了追求最好成绩一直预判。
如果已经开始猜“差不多该变绿了”,测到的东西就和第一次自然反应不完全一样了。
第三,尽量固定设备。
手机、鼠标、键盘和不同显示设备都会让最终数字产生一些差异。
第四,看平均,也看变化。
最好成绩适合挑战自己,但平均和近期记录更适合观察自己的正常状态。
反应速度多少才算快?
这是做这个页面以后经常会想到的问题,但我现在反而不太喜欢给一个绝对分界线。
原因很简单:不同测试的实现、设备、输入方式和测试环境都不完全一样。
如果直接写:
低于 X ms = 非常优秀
X~Y ms = 正常
超过 Y ms = 很慢
看起来非常清楚,但很容易给人一种这些数字具有统一标准的错觉。
我更喜欢先看自己的多轮结果,然后在相同环境下观察长期变化。
反应测试可以很好玩,也可以成为一个简单的个人基准,但没有必要把一次网页测试的数字理解得太重。
它更像一个“小型个人基准”
后来我把反应、记忆、瞄准、视觉追踪、时间感知和空间想象这些测试慢慢放到了一起,做成了一个中文人类基准测试小站。
但即使现在已经有多个测试,我自己仍然最喜欢反应测试这种非常简单的玩法。
因为它几乎没有学习成本。
等待。
看到。
点击。
然后得到一个数字。
简单到任何人都知道怎么玩。
但真的测几次以后,又很容易开始问:
为什么我这次慢了?
为什么手机和电脑不一样?
最好成绩重要还是平均成绩重要?
再测一次会不会更快?
一个只有几秒钟的小游戏,最后反而能产生不少值得思考的问题。
这可能也是我一直没有把它当成“做完了”的原因。
现在如果让我重新概括这个反应测试,我不会说它是在回答:
“你的反应能力是多少?”
我更愿意说:
“在当前设备和当前状态下,你这一次反应了多快?”
然后下一次回来,再测一次。
看看有没有变化。

Top comments (0)