随着硬件快速的发展,Retina技术发展至今,目前Google Nexus6的devicePixelRatio已经到了3.5,虽然目前主流的Retina显示器还是以devicePixelRatio = 2的为主,但是为了更好的用户体验,前端和视觉同学经常都要为了各种图标能够在Retina屏幕下高清显示而头痛。下面先介绍下目前的一些常规的解决方案。
1.多倍图片
目前用的比较多的做法是兼容devicePixelRatio = 2 就做实际图片大小的两倍,devicePixelRatio= 3就做三倍,有些人可能会直接做3倍的图片,这样就可以同时兼容devicePixelRatio = 2 ,但是这样其实对于devicePixelRatio = 1和devicePixelRatio = 2的用户他们就会浪费带宽去加载devicePixelRatio = 3的图片,所以为了提升用户体验,一般我们会分开做几套图片,根据用用户的devicePixelRatio判断让他们加载对应的图片。
2.Iconfont字体图标
在很多国外的响应式站点里一般会采用iconfont,因为可以直接通过font-size和color属性来控制icon的大小和颜色,非常方便,而且由于iconfont本身就是字体文件,会矢量适配各种不同devicePixelRatio,但是在PC上当图标小于等于16px时,或者复杂度高的图标会出现比较严重锯齿,图标无法展示清晰,特别在chrome下的表现尤为严重。正因为如此这个技术在推进过程中遇到许多困难,因为在很多场景下图标确实会较小甚至小于16px,而且有些16px的图标如果复杂度较高,iconfont实现出来的icon会经常出现看不清的情况,而且国内PC用户是占最多的,所以iconfont的这种表现效果很多用户和设计师无法接受。
为什么Iconfont会出现锯齿?
这个问题其实并不是iconfont的错,但很多人都觉得是它的问题,关于锯齿问题,我们先来了解下浏览器的字体渲染机制,阿里有篇文章《字体图标制作详解》里有一部分关于早期字体渲染机制的说明,内容如下:
(从左到右依次)理想的渲染状态、黑白渲染、灰度渲染、次像素渲染
上图左侧第一张是我们认为一种比较理想的渲染效果,但是通过刚才我们介绍栅格我们可以了解到这种状态是不可能的,因为第一代黑白渲染和第二代灰度渲染是不可能做到显示半格像素或一个像素中显示弧度的。
黑白渲染和灰度渲染在渲染图形遇到半格像素或则弧度的时候,他们会有各自不同的处理方式;
举个例子:
如上图红点处像素,我们理解他是有弧度的,且不占满一个像素;各个渲染方式的处理办法如下:
黑白渲染
黑白渲染相对来说比较粗暴,直接通过四舍五入的形式把这里要描绘的图形不显示了;(黑白渲染的形式主要应用于打印机渲染,但是打印机本身的精度非常高,所以打印出来的图形还是很细腻的)
灰度渲染
灰度渲染显得就智能一些了,他通过灰度降级的方式来表达,如果占不到一个像素那就根据他占的面积来降低这个像素的灰度;占的面积越小灰度就越低;
次像素渲染
次像素渲染是第三代渲染方式,相对来说比较高级,他从从左至右将一个像素分成三份;用不同的色彩值来显示图形,这样图形看起来就更加细腻;
现代浏览器字体渲染技术
目前mac系统采用的就是次像素渲染技术,但是现代的window下的高级浏览器例如:IE9+ 、chrome、FF等浏览器采用的是 DirectWrite 或 GDI 这种更高级的字体渲染技术,这里我简单介绍下这两种新的字体渲染技术:
上图从左至右分别用的是:灰度渲染、次像素渲染和 DirectWrite 或 GDI 实现的效果,在FF官方博客中有一篇文章对这两个新的渲染技术做了简单的一个解释,他们两个都是采用的LCD的像素红色、绿色、蓝色来进行像素填充,右侧的文字被放大后我们看到了字体栅格被不同色块填充,其实人眼对于亮度差异非常的敏感,当这些颜色用在像素级别里面我们的眼睛往往认为字形比单纯灰度消除锯齿的效果更好。
在Windows下的Firefox 4中采用的就是GDI这个技术进行字体渲染的,但是到了Firefox 4+之后的版本开始使用了DirectWrite这个技术,官方解释是说DirectWrite支持硬件加速,而且API也更加现代,而GDI API存在许多缺陷和问题。
关于DirectWrite和GDI他们之前的差异这里不作太多描述,在文章最后有相关文章链接,有兴趣的同学可以查看下。上面讲了字体渲染的历史,我们现在来看看目前Windows系统下的浏览器各自都是采用的都是什么字体渲染机制:
Chrome目前依旧是使用GDI,而FF和IE9+已经是采用了DirectWrite,这就是为什么iconfont在Chrome下锯齿会比其他浏览器严重的原因,可能GDI确实像FF官方说的存在许多缺陷,不知为何Chrome至今还在继续使用这个技术。
上面说了这么多关于字体渲染机制原理,在这里能得出一个结论: 不管目前使用什么字体渲染技术,字体显示效果始终是会出现锯齿的。在Retina屏幕上,一个像素被拆成了4个像素,由于它的密度非常高,肉眼根本是看不出锯齿的,所以现在MAC系统下的FF和Chrome都还是用的次像素渲染这项技术。既然iconfont他是一个字体,就难逃出现锯齿的命运,特别在Chrome下就是更加的糟糕了,目前确实通过前端代码也是无法改变这个缺陷。
iconfont由于这个严重的锯齿缺陷导致一些大型的站点很多时候并不会考虑大规模使用它,例如QQ空间,腾讯云这些站点早期也都尝试过iconfont方案,但最后都放弃了,为了能给用户更好的感官体验。像淘宝虽然目前有许多地方都用了iconfont但也只是局部使用,并非全站使用。
SVG技术
什么是SVG? SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式。SVG是W3C制定的一种新的二维矢量图形格式,也是规范中的网络矢量图形标准。SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。简单的说他就是一个可伸缩矢量图形 (Scalable Vector Graphics),在浏览器中采用绘图技术。
接下来我们来看看使用iconfont和使用SVG做出来的图标有什么差异:
Chrome下效果
FF下效果
IE9下效果
上面的demo分别在不同浏览器下的效果,第一行用的是iconfont实现,下面三行都是用的SVG实现的图标,只是调用SVG时的方法不同:第一行是用inline SVG,将SVG直接写在html中来使用,第二行是用的img标签去调用SVG,第三行用样式的background来调用SVG文件。从Chrome和FF下的显示效果,我们看到SVG画的ICON的质量确实是比iconfont要好,iconfont做的图标,我截图后放大后看到线的边缘发虚了,这是因为字体渲染的原因导致,在FF下也是发虚,只是不那么明显。在IE9+下的效果上我们看到IE对SVG的支持性着实差的令人无法直视,IE10,IE11效果和IE9几乎一样(真的是坑爹)。
如何绘制高质量ICON
在上面的demo中眼尖的同学应该可以看出在FF下,inline SVG图标有一个出问题了,然而Chrome却是正常的:
但左边那个图标却是正常的,相当不科学,如果是渲染问题理应左边的也发虚才对,但是却只有右边的出问题了,定位了很久问题出在哪里,最后发现是画AI文件时出问题了,AI本身不像PS那样,有网格辅助视觉画图,所以iconfont.cn出了一个AI模板,其实这套模板就是给AI画了一套辅助线,帮助设计师按照栅格画ICON,我前面的案例就是用的他们提供的模板画的图标,第一个没问题,但是第二个出问题了。他们这套AI模板实际导出后的画布大小是1002px1002px,然后分成1616个格子,也就是每个格子实际分得62.625px*62.625px,其实在很多时候貌似不会出问题的,但是我的demo中却出问题了,于是猜测:
是否是绘制图标出问题了,没有按照某种规范画法? 是否是因为他的网格不能被整除导致的?
1、由于绘制这个锁型的图标时我们留下了一个单数列,会不会因为这样导致了他出现锯齿,如果是,那问题就来了,如果一定要左右对称或者每次画图都要铺满所有格子,这种做法不太现实,因为很多图标是不一定都全部能铺满16*16的格子。
2、发现iconfont这套模板的网格有些问题,画布网格竟然有1px像素是留空的,也是说16格子其实是1001/16=62.5625px,虽说画布是1002px,不知道这是否是人工失误。
决心和视觉自己做一套AI模板,AI模板也是1616的网格,但是每个网格将他们的实际导出像素设置成1px,也就是整个画布是16px16px,这样的就不怕不会被整除了。然后用新AI模板重新做了三个图标,进行测试,左右上下对称的做了一个,不能左右对称的做了一个,左右上下不能对称的也做了一份。,然后导出效果查看:
按照这套模板做了图标后,FF下面三个图标都是完美的,没有出现虚边,并且Chrome也同样是完好的,这是我们希望看的的。也证实了上面的两个问题猜测是正确的。所以这套AI模板是完全可以满足不同场景图标绘制。
小结:
本文介绍了字体渲染机制,并分析iconfont出现锯齿的底层原因,再到如何绘制高质量SVG ICON的步骤和输出了一套严谨的AI绘制图标模板。
(编辑:小酷)
扫码添加客服微信
扫码关注公众号
酷网(大连)科技有限公司
致力于为客户品牌提供完善解决方案
统一服务电话:0411-62888851