Sketch中的文本处理方式

Sketch在前几个版本中的文本处理方式一直为使用者诟病,比如我们经常会看到的文本行间距问题,特别是在中文文本中格外明显,在bohemiancoding团队推出Sketch3.6版本的同时,他们同时写了一篇深入解析文字知识的文章 ,深度好文,让我们一起来理解系统中文字排版的原理以及sketch所作出的改善。对于字体问题,最后一段点题的文字也是静电想告诉大家的,请不要过分纠结文本框像素出现的1-2个像素的偏差,因为你的设计稿中的信息复现到真实的APP或者页面上的时候,不同设备的渲染方式也会产生差别,那么在这个环节,我们可以再根据主流设备,对你设计的界面做视觉走查,确保你想要的,就是你设计的。

文本和颜色一样,从表面上看起来非常简单,可一旦深究他们,你会发现并不是想象中的那样。多年以来,我们发现设计师所希望的文字排版系统,与苹果和其他字体供应商所构建的文字排版系统并不完全一致。

Sketch处理文本的方式我们一直列在想要改善的任务列表中,但是随着往下读这篇文章,你会马上发现进行这些调整需要我们深入研究苹果的这套文本渲染系统,并且需要做一些底层的调整。最终我们取得了进展,希望你能喜欢这种调整方式。

要了解这些待解决问题,首先让我们来看看Sketch对于文本图层的垂直度量要素。


单行文本图层的高度取决于这种字体大小的行高值。这个值并不与文字的真实大小匹配,并且对于不同的字体也会产生差异;有时它几乎与文字的字号一致,有时图层高度则是字号的两倍。因素主要是这个字体在其空间内的绘制方式,也就是由该字体所指定的基线(Baseline,如上图红色部分)所决定。

由于这个因素在不同字体之间的差异很大,所以当你在Sketch里调整不同字体,尤其是当你把多种字体和字号混合在同一个段落中的时候,Sketch对这些文字的处理就会产生戏剧性的变化。这样做的另一个不好的影响就是,当你在不同字体间切换时,画布上的字体经常会出现上移或者下移的现象。

经常出现在我们支持邮件中的问题,会问到说:为什么Sketch会出现看似空白的区域(如上图蓝色的区域),以及为什么字体边框没有紧贴在这行文字的上边缘和下边缘?这同样取决于字体本身的度量方式,简单的说,这部分蓝色空间会被一些字体的附加符号所使用,比如音标及修饰符。上标可能出现在一个大写的 S上边 (Š, 在捷克或者斯拉夫语言中可见到),下标呢,可能会在a下面出现一个小写字母c作为变音符号(ç, 在土耳其语和法语中最常见),这是很多文字中的两个比较典型的例子。

在Sketch3.6版本中,我们对排版文字图层的方式做了一些调整,特别是对于有固定行高的段落。要了解它是如何工作,以及做了哪些变化,我们需要了解一下苹果的文字系统,看看这种文字系统如何规定我们的文本行,以及它怎么运用在Sketch中。

字符和字形

排列文本段落的第一步就是将文本中的字符和文字属性转化成符号。符号是一个或多个给定字体的视觉表示方式。字符和文字之间的映射并不是1:1呈现的。举个例子,一个独立的图像字型会代表不止一个的字符,这就是连笔字。字符的排序不同,就会产生不同的连笔字,这就会产生不同数量的图形符号。“Zapfino” 我们遇到的最极端的连笔字,它存在于Zapfino字体中,这七个字符由单个图形表示。

文本容器和文本行片段

一行可以容纳多少个图形字符取决于文本容器的宽度。在Sketch中,文本容器的尺寸取决于文本图层的宽度。要使用图形字符填充文本容器,我们需要将它们截断成行。这种包含所有图形字符并适配成为单独一行的矩形,我们称之为“行片段矩形(line fragment rectangles)”。只要在段落内使用单一一种字形或者字号,这时一切都看起来和你预想的一模一样:


在Sketch中,使用混合字形和字号的段落经常看起来并不是那么理想。尽管我们设置了固定的行高,但是问题出在哪里呢?答案就是要找到在这个行片段中,文本控制器选择哪里作为这行的基线(baseline)位置。

事实上,在每一个行片段中,Cocoa的文本控制器会先从文本行片段的最底部找到这一行最高的下标字符,然后使用它作为基线的边缘。对于混合字体,虽然行高是固定的,但不同字体的基线却并不相同。(静电注:Cocoa是苹果公司为Mac OS X所创建的原生面向对象的API,是Mac OS X上五大API之一)


当设计师在设置文本行高的时候,比如20pt,他们会认为这20pt是每一个基线之间的距离,并不是行片段矩形的高度为20pt。这种说法是有道理的,因为决定文本视觉垂直节奏的是基线,这个基线,是比前文所说的抽象的“文本矩形片段”更具象的也可观察到的。那么,我们要如何解决这个问题呢?

一致的基线位置


在Sketch 3.6中,我们引入了一种全新的文本控制器,这种文本控制器可以在固定行高的情况下,为段落产生一致的基线位置边缘。为了让它正常的工作,我们让所有的段落片段和选择内容都进行了基准偏移,以适应文本的排版。

同样,只要设置了固定的行高,那么在段落之间,甚至是不同的字体之间,这种特性也会被保留。但是如果没有设置固定行高,这时系统会使用字号作为行高(静电注:大家可以试一下调整文字的字号,看看行高数值是否会随之变化)。一旦你设置为固定行高,这时你将会得到一段漂亮的,并且可以被预测到的文本展示效果:


那如何兼容之前版本生成的文档内容呢?新创建的文本图层会默认使用上文提到的新的文本控制器,老版本Sketch中生成的文本图层,如果想要达到这个效果,只需要重新设置一遍行高数值即可。(静电注:如你没有在新版本Sketch中重新设置,则这个文本图层不会做出任何变化。)

其它改进

我们对于行高的改进同样对这样的操作产生的影响:那就是当你设置段落的行高数值要小于文字本身的字号的时候,因为基线总是位于文本片段矩形内。同样,他会提高了文本图层的选择边框矩形的大小。

最后,如果在文本图层中改变字体,我们已经使用了一些方法来确保程序使用第一条基线的位置,所以当你在字体间进行切换的时候(即更换字体),文本图层不会再垂直左右的跳跃了。

最后要注意的内容

你可能已经注意到了,数字排版技术是一个非常复杂的课题。同样,我们生活在一个快速变化的时代,它如此激动人心,以至于你所设计的设计稿所呈现出的效果,不可能在所有设备和平台上都保持完全精确的匹配。

对于我们来说,要创建一个系统,确保渲染出来的字体能精确的和iOS,Android,Windows下的Chrome,或者Mac下的Safari的显示效果完全一致,这是不可能的。每个系统对字体和图形的渲染都有很大的差异,也非常复杂,保持精确的像素一致性几乎不可能。

我们一直在倾听你的反馈,并致力于创造一套一致性和可靠性兼具的渲染系统。在这次大版本的更新中,我们花了大量的时间用来改善字体和行距问题,但它只是个起点,这是今年我们打算要发布的改进中的第一部分。

2020-10-21