如何让svg图标始终对齐到像素
2020-11-26 14:35:06    51    0    0
emengweb

为解决图标1x、2x、3x多种尺寸的问题,大家经常会想到svg或者iconfont图标库。这里我们不比较svg与iconfont两种形式的优缺点,单独对svg图标库进行研究,找到它的不足,并给出弥补这种不足的解决方法。


首先明确一下svg图标的优点,这也是我们舍弃传统的位图,使用svg图的原因所在:


• 图形自由缩放不发虚

• 图形大小可通过CSS自由控制

• 图形颜色可通过CSS自由赋予

• 图形的不同区域可赋予不同颜色

• 同一图形可通过改变大小及颜色用于不同场景



也就是说,只要图形形状没发生变化,那就只需要一个svg图,而不会出现像位图那样即便形状完全一样,只要大小、颜色任意一项发生变化就需要输出一套新图标的情况。举个例子,假设我们已经给开发同学提供了一个加号svg图标,并用于tab bar上,大小为24*24,颜色为#FFFFFF,若有其他情况也需要用到这个加号图标,但大小跟颜色都有所不同时,我们不用再重新切图,只需要将尺寸及色值给到开发同学,开发同学继续调用这个svg图标,并赋予新给出的大小与颜色。这样会大大的降低图标维护成本,提高设计与开发之间的协作便利性。


svg虽说是矢量图形,放大缩小都不会影响图形本身的锐利程度,但受限于屏幕显示机制的原因,如果图形缩放一定倍率后,边缘没有对齐到像素,屏幕显示时还是会模糊、不锐利。其实从本质上说,这并不是svg的原因,因为不管在缩放什么倍率,svg图形本身是不会模糊或者虚化的,只是因为屏幕的显示机制缺陷,才造成了svg图标在一些情况下看起来模糊不清。而我们要做的工作,就是通过控制svg图标的部分特性,来实现对屏幕显示缺陷的规避,进而实现清晰锐利的图标显示效果。


我们发现,svg图标在缩放过程中,有几个关键因素可能会影响到图形的显示效果:图标绘制尺寸L、缩放倍率i、线宽b、绘制时安全区宽度p,如下图

Image title

 

虽然图标绘制尺寸L可以是任意值,但基于绘制及使用的方便性,我们一般设定为整数。而若想缩放后的尺寸依然是整数,则需要保证缩放倍率为整数或部分特定的小数,比如L值为为5的倍数时,部分小数倍率值如n.2、n.4、n.6、n.8也可以满足缩放后为整;L值为偶数时,则小数倍率n.5也可以满足缩放后为整。但绘制尺寸是否为整数,并不影响图标的清晰锐利程度,我们只是为了绘制或使用的方便性人为将其设定成整数。影响图标是否清晰锐利的关键因素是,绘制时线宽是否为整或n.5、绘制时安全区宽度是否为整或n.5、形状边缘是否对齐到像素或0.5个像素、缩放后线宽是否为整或n.5、缩放后安全区是否为整或n.5,同时满足以上所有因素才能保证图标缩放后显示清晰锐利。基于这个原因,当L值为5的倍数的奇数时,线宽只有满足5的整数倍或n.5倍时才能实现n.2、n.4、n.6及n.8的小数倍率下为整数或n.5,显然2.5、5、7.5…的线宽对于图标而言有些太宽了,基本没有可用性。而剩余奇数如9、11、13、17、19等,要么因为太小如9、7、5等不方便绘制,要么因为只支持整数倍率缩放,造成图标尺寸跨度过大,比如L值为11时,图标尺寸序列为11、22、33、44…其中可用的图标就只有22与33,11太小44又太大。所以,我们可以得出一个结论,L值不能为奇数,也就是说L值只能为偶数。


可能有同学会问为什么n.5也能满足,这里补充一下,因为绘制图标时一般使用sketch软件,并将画板设定为x1尺寸,所以当图标线宽或绘制时安全区宽度为n.5时在X2后依然可以得到整数,自然可以保证边缘对齐到像素。但如果是针对web的设计,尽量对齐到整数像素,毕竟高清或retina屏电脑还没有达到手机高清屏的普及程度。


接下来我们通过详细的数据计算、验证,提炼出一些通用规则,方便大家使用。


目的:一套svg图标满足一个产品所有图标需求。

难点:保证放大或缩小后的图标边缘全部对齐到整数或.5个像素。

影响因子:图标绘制尺寸L、缩放倍率i、线宽b、绘制时安全区宽度p。

画板尺寸:375*667、375*812



正文:


图标类型分为线型、面型、线面接合型三种,三种图标影响像素锐度的因子有所不同。

线型影响因子:图标绘制尺寸、缩放倍率、线宽、绘制时安全区宽度;

面型影响因子:图标绘制尺寸、缩放倍率、绘制时安全区宽度;

线面接合型影响因子:图标绘制尺寸、缩放倍率、线宽、绘制时安全区宽度;

其中线型与线面型因为影响因子相同可以归为一类,视为一种。


一、图标绘制尺寸L与缩放倍率i


我们发现,设计时常用图标尺寸一般在12-36px之间。为了方便绘制的时候查看页面效果,我们可以从中选择一个尺寸作为绘制尺寸,然后通过设定缩放倍率来获得其他尺寸的图标。

因为L值只能为偶数,所以可选的L值有12、14、16、18、20、22、24、26、28、30、32、34、36。如果要满足所有缩放后的图标尺寸也是偶数,则需满足图标尺寸是4的倍数,即可选L值为12、16、20、24、28、32、36。


• L=12时

Image title

所以,可用icon尺寸为:12、18、24、30、36


• L=16时

Image title

7所以,可用icon尺寸为:16、24、32


• L=20时

Image title

所以,可用icon尺寸为:20、30


• L=24时

Image title

所以,可用icon尺寸为:12、16、24、36


• L=28时

Image title

所以,可用icon尺寸为:14、28


• L=32时

Image title

所以,可用icon尺寸为:16、32


• L=36时

Image title

所以,可用icon尺寸为:12、18、24、36


综上,L=20、28、32时可用尺寸数太少,不宜使用,我们可选的L值为12、16、24、36。其中L=12或16时,最小值即为绘制值;L=24或36时,L为中间值,分别向上递增向下递减速。


L=12时,可用尺寸为:12、18(x1.5)、24(x2)、30(x2.5)、36(x3);

L=16时,可用尺寸为:16、24(x1.5)、32(x2);

L=24时,可用尺寸为:12(x1/2)、16(x1/1.5)、24、36(x1.5);

L=36时,可用尺寸为:12(x1/3)、18(x1/2)、24(x1/1.5)、36



二、绘制时安全区宽度p


图标绘制尺寸L及缩放倍率i确定后,相当于可用图标尺寸已全部确定。这时我们还需要保证图标绘制时安全区宽度p在做相应缩放后为整数或者n.5,且当p=n.5时,缩放倍率i≠n.5,否则会出现.25或者.75的情况,无法对齐到像素。而我们前文也验证了,若不能采用n.5倍率,可用图标尺寸会比较少且图标尺寸跨度比较大,不能满足现实需求。因此,绘制时安全区宽度p≠n.5,p只能取整数


当L=12或16时,绘制时安全区宽度取1或2时都能满足缩放后对齐到像素或者.5像素;但当p=2时,安全区面积所占比例分别达到了55.56%和43.75%,造成绘制区域过小,不符合要求,所以绘制时安全区宽度p只能取1。


当L=24时,L为中间值;若p=1,则向下计算时,12、16尺寸下绘制时安全区宽度分别为0.5和2/3,无法对齐到像素,不符合要求;若p=2,则向下计算时,16尺寸下绘制时安全区宽度为4/3,无法对齐到像素,不符合要求;若p=3,则向下向上皆可对齐到像素,但是安全区面积所占比例达到了43.75%,造成绘制区域过小,不符合要求。因此L=24时,不能满足设计需求。


当L=36时,L即为最大值;p=1或2时,12、18、24至少同时有2个不能满足对齐到像素;p=3时,12、18、24时安全区宽度分别为1、1.5、2,都能对齐到像素或.5像素。


因此,在满足p值符合要求的前提下,可用绘制尺寸L只能取12、16或36三种,12与16时p值为1,36时p值为3。另外我们也发现,L=12或36时,结果已基本趋同,且L=36的结果被包含于L=12的结果中,所以可选L值可以缩减为两种,分别为12及16。


综上,

L=12时,p=1;

L=16时,p=1。



三、绘制时线宽b


因为缩放倍率i一定会有等于n.5的情况,为保证缩放后线宽都对齐到像素,就要求绘制时线宽b必须像p值一样必须取整数,所以

L=12时,b=1、2、3…

L=16时,b=1、2、3…



四、结论


4.1、若绘制面型图标

L=12时,p=1,i=1.5、2、2.5、3,可选图标大小为:12、18、24、30、36;

L=16时,p=1,i=1.5、2、2.5,可选图标大小为:16、24、32、40;


4.2、若绘制线型图标

L=12时,p=1,b=1、2,i=1.5、2、2.5、3,可选图标大小为:12、18、24、30、36;

L=16时,p=1,b=1、2、3,i=1.5、2、2.5,可选图标大小为:16、24、32、40。



五、延展


是否可以基于2个L值绘制图标?

即我们可以选取12与16,或者16与24两个L值来绘制图标,这种情况下我们只需要保证缩放倍率为整数即可,也可以获得满足设计需要的不同icon尺寸。比如:

L为12与16时,可得图标尺寸12、24、16、32;

L为16与24时,可得16、32、12、24;

但是基于两个L值进行图标绘制时会产生两种尺寸的svg图标,增加维护和使用成本,还容易出现同一图标两种尺寸的情况,造成图标冗余。好处是方便图标绘制,提高图标的绘制便捷性。

L=12与16,或L=16与24时

安全区为1.5时,一则不方便图形绘制,二则16px下安全区为1.5会造成安全区占比过大,故方便起见,在12与16的情况下,安全区都设置为1。

Image title

也就是说如果绘制时L值取两个,安全区宽度p的设定可以固化为基于12与16大小情况下都为1,基于24的则为2;而线宽b的值可以根据绘制风格从上方表格中自由选取。

上一篇: 安装docker和docker compose

下一篇: Manjaro安装系统后的必备操作

51 人读过
文档导航