让符号出现时文字也不会抖动的方法
你是否遇到过,仅仅把光标移到列表项上,整段文字就向旁边晃动了一下?只要是会隐藏和显示符号的编辑器,几乎都会遇到这种情况。

为了编辑列表而移动插入符时,文字会被挤到一旁。插入符移开后,文字又会回到原位。
虽然移动的只有一行,但看起来却像整个段落都在晃动。这个细微的差异不断打断编辑的节奏。
原因在于标记的宽度。
平时画面上显示的是圆形项目符号。但文件中保存的是连字符和空格。当插入符碰到标记时,为了能够直接修改,就需要显示原文。
问题在于这两种形态占据的宽度不同。项目符号是一个宽度固定的方框,但连字符和空格的宽度会因字体而异。在 mote 中,这个差值是 4.9 px。每当原文显现时,后面的文字就会被挤开这么多。
按照宽度差移动整行
我们没有让两者的宽度变得完全相同,而是抵消它们之间的差异。
在标记切换成原文的瞬间,将整行朝相反方向移动相当于宽度差的距离。即使符号的形态发生变化,正文开始的位置也保持不变。
不会改动文件。项目符号只是覆盖绘制在连字符上方的装饰,而校正只会改变画面中绘制这一行的位置。无论插入符进入还是离开,保存的内容都保持不变。
计算宽度的基准也统一成了一个。以前,绘制标记的地方和校正行位置的地方分别使用了不同的数值。两个值之间的细微差异,正是那 4.9 px。
现在,两处都会通过同一个函数获取标记的宽度。因为基准只有一个,所以也不会再出现偏差。
不过,如果左侧留白不足,就不会进行校正。因为移动这一行后,文字可能会被裁切到窗口之外。相比晃动,文字消失是更严重的问题。
标题和引用仍然会被挤动
最初,我们也对标题和引用采用了相同的方法。
但标题的 # 和引用的 > 平时在画面中占据的宽度是 0。要固定正文,就必须把符号移到左侧留白区域。
从技术上来说,它运行得很好。文字确实不会移动。但画面看起来很陌生。符号单独悬在留白区域的样子并不自然。
所以我们撤销了这个改动。现在,当标题和引用的符号显现时,正文会向右移动。

最终,我们为每种标记选择了不同的答案。
像项目符号和待办事项复选框这样在画面中有方框的标记,会固定正文。像标题和引用这样平时宽度为 0 的标记,则会挤动正文。
相比统一的规则,自然的画面更重要。
只在确实需要时显示符号
减少晃动的最佳方法,是减少符号发生变化的时刻本身。
现在,只有当插入符位于项目符号上时,才会显示其原文。当插入符越过空格移到正文中时,它会立刻恢复为项目符号。修改列表内容时,没有必要一直看到连字符。
即使一行变长并换到下一行,也会保持对齐。在标记以原文形式显示期间,第二行仍会从第一行正文的下方开始。
我们还修复了点击被误判为拖动的问题。在标记发生变化的瞬间,如果指针轻微晃动,文字有时会被选中。现在,只有当指针移动超过 8 px 时,才会判定为拖动。
用数字而不是眼睛来确认
这种差异很难只靠眼睛确认。短暂看起来可能没有问题,但长时间使用时会让人感到散乱。
因此,我们编写了启动实际应用的测试。将插入符移入和移出标记,并直接比较正文开始位置的 x 坐标。只有两个值相同,测试才能通过。
项目符号、待办事项复选框和嵌套列表都会用同样的方式进行检查。
一个像素的偏差很难被报告为 bug。因为用户与其解释究竟是什么在移动,更多时候只会觉得“莫名有些散乱”。
所以,这类移动应该由数字而不是人来监守。
安静的画面并不是什么都没有发生的画面。它是让必要的变化发生在不碍眼之处的画面。