一次滑动里的三件事:Telari 怎么打磨滚动手感
作为Telari的作者和用户,其实一直隐约觉得不是特别跟手,这个问题一直困扰着我。因为滚动恰好是我们花了最多心思的地方之一,帧率、掉帧、首屏时间都有专门的仪器盯着,数字一直很好看。但手的感觉不会骗人,也有其他用户给我反馈这个问题。最近我终于找到了一个藏了七周的问题。今天0.5.7发布,这个问题已经修好了,我装上之后第一感觉是:滚动的手感确实大幅改善。
借这个机会,想跟大家聊聊Telari在滚动这件小事上做过的事情。
为什么是滚动
Telari是阅读器,没有编辑功能。一个人打开一篇文档之后,做得最多的动作不是点按钮,不是搜索,而是滚动。一篇长文读下来,手指可能要在触控板上滑几十次。
所以对阅读器来说,滚动不是一个功能,而是整个体验的底色。排版做得再讲究,如果滑起来有一点顿、有一点黏,读的人不一定说得出哪里不对,但会觉得不舒服。
我们把滑起来顺不顺拆成了三层:画得够不够快,排得够不够快,以及画面能不能紧紧跟住手指。这三层,Telari各打磨了一轮。
第一轮:让每一帧只做最少的事
现在的Mac屏幕大多是120Hz,也就是说每一帧只有8毫秒的渲染预算。只要有一帧没赶上,眼睛就能感觉到一下轻微的顿挫。
今年7月我们做了一次仔细的调查,结论出乎意料:Telari画一屏文字其实很快,快到绰绰有余。真正拖后腿的是,新版macOS在滚动时会反复让程序重新交代「这一块该画什么」,即使内容根本没变。
于是我们换了一种思路:把已经排好的内容提前画成一条条「胶片」,滚动的时候只是把胶片平移,而不是重新作画。胶片快滑出屏幕时回收,再在前方补上新的一条。手指往哪个方向滑,就提前往哪个方向多备几条。
这样一来,滚动的每一帧几乎什么都不用做,只是挪一挪位置。
第二轮:卡顿的真身是「第一次看见」
胶片方案上线后,还剩一个现象:把文档从头到尾拖一遍之后,再怎么滑都很顺;但第一次往下读的时候,偶尔还是会顿一下。
原因是排版。Telari的排版比网页要讲究得多:每一段都要计算最佳断行、调整字词间距、处理中西文间距和标点压缩。这些计算单次并不慢,但如果恰好发生在滚动的那一帧里,就会变成一次可以感知的停顿。
我们的做法是让排版提前一步:当你停下来阅读的时候,Telari在后台悄悄把前后的内容排好;你一动手,它立刻让路,不和滚动抢时间。
这一轮我们还拿一本10 MB的长篇小说做了极端测试,三万多个段落。改进之前,打开要先把整本书排完,十几秒;改进之后,只排你正在看的那一章前后,打开到看见第一屏只要74毫秒。快速滚动时,每10秒的掉帧从156次降到了1次。
读一本书,不需要先把整本书排完。
第三轮:一个只有手能感觉到的问题
到这里,画和排都已经很快了。那点「不跟手」,又是从哪里来的?
答案藏在一个很不起眼的地方。macOS有一套专门为滚动优化的机制:系统会在后台直接处理滚动手势,即使程序正忙,画面也能及时跟上手指。这套机制默认是开着的,但有一个条件——程序如果自己接管了滚动事件,就需要明确告诉系统「我不会打扰你」,否则系统会保守地把它关掉。
8月的时候,我们给超宽的数学公式加了一个功能:公式太宽、窗口放不下时,可以用两指左右滑动来看完整个公式。为了实现它,我们接管了滚动事件,但少写了那一句「我不会打扰你」。
从那天起,每一次上下滚动都比原来慢了一拍。
这个问题最难的地方在于,它几乎没有任何可以被发现的痕迹:没有报错,没有崩溃,截图逐像素相同,几千个自动化测试全部通过,帧率测试的数字也一样漂亮。唯一的症状是延迟,而延迟,敏感的人很容易感觉出来。
修复本身只有一行。我们也加了一道检查:以后任何地方再接管滚动事件,都必须明确回答这个问题,不允许沉默。
修好一个,又牵出一个
候选版用了几个小时,我又发现了新问题:上下滑确实好多了,但公式左右滑变得不太灵了,手越抖越难滑开。
这次我们没有靠猜。Fable在虚拟机里模拟出和我的触控板一模一样的手势信号,把旧版和新版放在一起,同一串手势逐帧对比。结果发现,旧的系统行为里一直存在一个没人注意到的「空档」:斜着滑、又不够横的那些瞬间,旧版什么都不做,新版则会把页面往下推。页面一动,公式就从指尖底下溜走了,整个横滑因此中断。
我又录下了自己真实滑动时的手势记录。对着这份记录,我们又发现了第二个原因,并把它们一起修好:现在只要手势从公式上开始,Telari会先看头几个瞬间的整体方向,再决定是左右滑公式,还是上下滚文档。手稍微有点抖,也不会被误判。
从第一次觉得不对劲,到两个问题都修好发布,一共三个候选版本。每一版都是我先拿来日常用,觉得对了才往下走。
手感没有标准答案
Telari的排版有LaTeX可以对照,公式的每个符号位置都能和成熟的排版引擎逐位比较。但「滑起来跟不跟手」没有这样的标准答案,它最终只能由人的手来判断。
我们能做的,是为每一层都造好仪器:一个随时可以打开的帧率面板,一套能自动驱动真实窗口的滚动测试,一份能记下每个手势去向的记录工具,以及能模拟不同设备和系统版本的虚拟机。仪器不能代替手,但它能让一句说不太清的「不太跟手」,变成一个可以被找到、被修好、并且不会再犯的问题。
回头看这三轮,每一次「卡」的真正原因,都不在第一眼看到的地方。这也是我越来越相信的一件事:好的体验不是某个功能,而是很多个没人注意的细节,被一个一个地认真对待。
我自己就是Telari最重度的用户,每天读的东西都在它里面,这类问题往往是在日常使用里「感觉」出来的。如果你在使用中也觉得哪里不舒服,哪怕说不清是哪里,也欢迎告诉我。
下载地址:telari.app