轩枫阁

首页 / Web前端 / CSS / 高清ICON SVG解决方案

高清ICON SVG解决方案

前言

随着硬件快速的发展,Retina技术发展至今,目前Google Nexus6的devicePixelRatio已经到了3.5,虽然目前主流的Retina显示器还是以devicePixelRatio = 2的为主,但是为了更好的用户体验,前端和视觉同学经常都要为了各种图标能够在Retina屏幕下高清显示而头痛。下面先介绍下目前的一些常规的解决方案。

1.多倍图片

目前用的比较多的做法是兼容devicePixelRatio = 2 就做实际图片大小的两倍,devicePixelRatio= 3就做三倍,有些人可能会直接做3倍的图片,这样就可以同时兼容devicePixelRatio = 2 ,但是这样其实对于devicePixelRatio = 1devicePixelRatio = 2的用户他们就会浪费带宽去加载devicePixelRatio = 3的图片,所以为了提升用户体验,一般我们会分开做几套图片,根据用用户的devicePixelRatio判断让他们加载对应的图片。

2.iconfont字体图标

在很多国外的响应式站点里一般会采用iconfont,因为可以直接通过font-size和color属性来控制icon的大小和颜色,非常方便,而且由于iconfont本身就是字体文件,会矢量适配各种不同devicePixelRatio,但是在PC上当图标小于等于16px时,或者复杂度高的图标会出现比较严重锯齿,图标无法展示清晰,特别在chrome下的表现尤为严重。

正因为如此这个技术在推进过程中遇到许多困难,因为在很多场景下图标确实会较小甚至小于16px,而且有些16px的图标如果复杂度较高,iconfont实现出来的icon会经常出现看不清的情况,而且国内PC用户是占最多的,所以iconfont的这种表现效果很多用户和设计师无法接受。

为什么iconfont会出现锯齿?

这个问题其实并不是iconfont的错,但很多人都觉得是它的问题,关于锯齿问题,我们先来了解下浏览器的字体渲染机制,阿里有篇文章《字体图标制作详解》里有一部分关于早期字体渲染机制的说明,内容如下:

20151103155405613

(从左到右依次)理想的渲染状态、黑白渲染、灰度渲染、次像素渲染
上图左侧第一张是我们认为一种比较理想的渲染效果,但是通过刚才我们介绍栅格我们可以了解到这种状态是不可能的,因为第一代黑白渲染和第二代灰度渲染是不可能做到显示半格像素或一个像素中显示弧度的。
黑白渲染和灰度渲染在渲染图形遇到半格像素或则弧度的时候,他们会有各自不同的处理方式;

举个例子:

如上图红点处像素,我们理解他是有弧度的,且不占满一个像素;各个渲染方式的处理办法如下:

黑白渲染

黑白渲染相对来说比较粗暴,直接通过四舍五入的形式把这里要描绘的图形不显示了;(黑白渲染的形式主要应用于打印机渲染,但是打印机本身的精度非常高,所以打印出来的图形还是很细腻的)

灰度渲染

灰度渲染显得就智能一些了,他通过灰度降级的方式来表达,如果占不到一个像素那就根据他占的面积来降低这个像素的灰度;占的面积越小灰度就越低;

次像素渲染

次像素渲染是第三代渲染方式,相对来说比较高级,他从从左至右将一个像素分成三份;用不同的色彩值来显示图形,这样图形看起来就更加细腻;

现代浏览器字体渲染技术

目前mac系统采用的就是次像素渲染技术,但是现代的window下的高级浏览器例如:IE9+ 、chrome、FF等浏览器采用的是 DirectWriteGDI 这种更高级的字体渲染技术,这里我简单介绍下这两种新的字体渲染技术:

20151103155405613

上图从左至右分别用的是:灰度渲染、次像素渲染和 DirectWriteGDI 实现的效果,在FF官方博客中有一篇文章对这两个新的渲染技术做了简单的一个解释,他们两个都是采用的LCD的像素红色、绿色、蓝色来进行像素填充,右侧的文字被放大后我们看到了字体栅格被不同色块填充,其实人眼对于亮度差异非常的敏感,当这些颜色用在像素级别里面我们的眼睛往往认为字形比单纯灰度消除锯齿的效果更好。

在Windows下的Firefox 4中采用的就是GDI这个技术进行字体渲染的,但是到了Firefox 4+之后的版本开始使用了DirectWrite这个技术,官方解释是说DirectWrite支持硬件加速,而且API也更加现代,而GDI API存在许多缺陷和问题。

关于DirectWrite和GDI他们之前的差异这里不作太多描述,在文章最后有相关文章链接,有兴趣的同学可以查看下。上面讲了字体渲染的历史,我们现在来看看目前Windows系统下的浏览器各自都是采用的都是什么字体渲染机制:

20151103155255900

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下效果

20151103155604104-590x529

FF下效果

20151103155656724-590x464

IE9下效果

20151103155722436-590x515

上面的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却是正常的:

20151103155311874

但左边那个图标却是正常的,相当不科学,如果是渲染问题理应左边的也发虚才对,但是却只有右边的出问题了,定位了很久问题出在哪里,最后发现是画AI文件时出问题了,AI本身不像PS那样,有网格辅助视觉画图,所以iconfont.cn出了一个AI模板,其实这套模板就是给AI画了一套辅助线,帮助设计师按照栅格画ICON,我前面的案例就是用的他们提供的模板画的图标,第一个没问题,但是第二个出问题了。他们这套AI模板实际导出后的画布大小是1002px1002px,然后分成16*16个格子,也就是每个格子实际分得62.625px*62.625px,其实在很多时候貌似不会出问题的,但是我的demo中却出问题了,于是猜测:

  • 是否是绘制图标出问题了,没有按照某种规范画法?
  • 是否是因为他的网格不能被整除导致的?

1、由于绘制这个锁型的图标时我们留下了一个单数列,会不会因为这样导致了他出现锯齿,如果是,那问题就来了,如果一定要左右对称或者每次画图都要铺满所有格子,这种做法不太现实,因为很多图标是不一定都全部能铺满16*16的格子。

20151103155315575

2、发现iconfont这套模板的网格有些问题,画布网格竟然有1px像素是留空的,也是说16格子其实是1001/16=62.5625px,虽说画布是1002px,不知道这是否是人工失误。

20151103155319262-590x468

决心和视觉自己做一套AI模板,AI模板也是16*16的网格,但是每个网格将他们的实际导出像素设置成1px,也就是整个画布是16px*16px,这样的就不怕不会被整除了。然后用新AI模板重新做了三个图标,进行测试,左右上下对称的做了一个,不能左右对称的做了一个,左右上下不能对称的也做了一份。,然后导出效果查看:

20151103155813280-590x123

按照这套模板做了图标后,FF下面三个图标都是完美的,没有出现虚边,并且Chrome也同样是完好的,这是我们希望看的的。也证实了上面的两个问题猜测是正确的。所以这套AI模板是完全可以满足不同场景图标绘制。

小结

本文介绍了字体渲染机制,并分析iconfont出现锯齿的底层原因,再到如何绘制高质量SVG ICON的步骤和输出了一套严谨的AI绘制图标模板。

 

前言

在上文中,我们讲述了字体渲染机制和导致iconfont出现锯齿的原因,以及如何才能出绘制高质量SVG ICON,并且提供了一套AI模版供大家参考使用。下文将讲诉前端侧我们如何用SVG来做成高清ICON,并且良好支持PC下的各个浏览器,并兼容IE6+以上的浏览器。

从上文中我们得知SVG 做的图标在IE9+的浏览器渲染效果相当的差,所以在IE下我们我们不使用SVG ICON,我们可以将SVG转成一倍的png图片来进行替代。首先来简单的普及一下SVG ICON的几个使用方法:

第一种Inline SVG

这种方法就是直接把SVG标签写入到HTML中去,直接通过修改fill和stroke属性来控制填充颜色和边框颜色,但是缺点就是维护性不好,如果一个页面Icon特别多,可能要写好几十个SVG在页面,复用性差,后期扩展性也不佳。

第二种img/object 标签

这种方法直接将SVG ICON保存成一个一个单独文件,通过img或object标签引用,他的缺点就是请求数增加,每个图标都去独自加载,对服务器负载和页面高速加载不好。

第三种background and Data URIs

在上一篇文章中我有一种调用方法就是采用background去调用SVG文件:

还有如果单独使用background引用SVG也会和第一种方案一样造成请求数增加,所以有不少人通过使用base64 编码来减少HTTP请求:

不过不太建议使用base64 编码,无论性能和维护方面都不是特别好,记得看过一个测试base64性能的文章,base64在移动端渲染时间比正常使用url的渲染时间要慢6倍。

第四种SVG Sprites

目前市面上有很多提供ICON FONT制作的网站,例如:icomoon不止开源,而且功能实在强大,可以提供输出SVG Sprites的功能,SVG Sprites它的使用方法其实就跟Png sprites是一样的,把多个SVG ICON合并到一个SVG文件里面去,然后通过background-position进行定位,这种方法可以解决请求数增多的问题。

当然如果你不喜欢用icomoon也可以用自动化工具生成SVG Sprite例如用:gulp-svgstoregrunt-iconizrgulp-svg-sprites

第五种SVG Defs/Symbols

这种其实就是在SVG Sprites上面更进一步的使用了,SVG Sprites是需要我们去通过坐标获取对应位置图标的,但是SVG Defs/Symbols就更简单了,直接通过给每个SVG ICON定义ID,直接调用对应ID即可:

将上面代码保存为SVG文件后,在HTML我们通过下面的方式可以直接调用:

新的方案:Svg Sprites +Png Sprites + Image-set

由于我们知道SVG在IE下的兼容性并不好,所以在高清ICON的适配在第四种方案的基础上进行优化,首先用icomoon进行下面的步骤操作:

第一步将用AI模板做好的图标转换成SVG文件后导入到icomoon中:

20151105130640894-590x239

第二步:

20151105130644602-590x369

第三步,设置导出文件前的类名,图标间距,颜色等等一系列参数,然后下载压缩包:

20151105130648344

第四步,只获取我们所需要的文件夹的内容:

2015110513065234-590x268

第五步,对icomoon生成的样式sprite.css进行微调整让其适配所有PC浏览器和Retina下的浏览器:

20151105130655853-590x266

最后的效果:

20151105130659589-590x462

CSS4 Image-set

这里应该有人会觉得也可以使用Media Queries来进行判断处理在Retinal来加载SVG Sprites,但其实Image-set它和Media Queries有些许,它不需要告诉浏览器使用什么图像,而是直接提供了图像让浏览器自己去选择加载合适的图片。兼容性方面在Safari6.1开始和Chrome21就开始支持这个属性了。

总结

SVG目前还是存在许多问题,Windows下使用IE的兼容性和渲染效果都太差,在PC侧我们无法全量使用,所以我们可以用上面的这套解决方案解决PC下所有浏览器下兼容问题,在Retina下,不管是device =2还是3都可以兼容,不管未来是否会有更高的devicePixelRatio出来,按照上面的方法都能完美兼容,并且在对应不同的devicePixelRatio下浏览器会自动选择加载SVG或者PNG,不会两张都同时加载。

上文之所以在火狐图标出问题那块讲了许久,并抛出更严谨的图标制作方法的主要原因这个方案需要对合并后的SVG Sprites转成PNG Sprite图片,如果SVG ICON做的有问题,那生成的图片也然出现发虚的情况,大家看我最后那个效果图下,PC下所有浏览下,中间那个锁的图标虽然是用的生成的图片但是依旧是发虚的和火狐下当时出问题的效果是一样。

AI模板下载链接

AI模板下载地址

参考自:高清ICON SVG解决方案 – ISUX

97/470
99/470

相关阅读

文章评论

  • 第五种方案如果图标要换色要怎么解决呢?

  • 文章质量依旧那么棒!

纸飞机许愿

x

钢琴节奏

请选择弹奏的曲谱

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2

    [返回曲谱列表]

    点击开始录制,可以录制弹奏的曲子