天气转暖了,冬日暖阳让人整个都舒展了,周五了,偷偷摸摸鱼,最近少有的晴天,周末户外走起
闲言少叙,开始正文
随着svg的浏览器兼容性越来越好,图标的使用基本已经都已经是svg方案了。笔者最近自己找麻烦,搭建了一个公司内部的svg治理站点,可以理解为一个私有化的阿里巴巴图标库。在对接历史svg治理的过程中,遇到了各种各样的问题。尤其是面对水平参差不齐的设计师的时候,导入到系统的svg也是五花八门的。除了需要在存储落盘前,将图标”洗干净”,还需要和设计师去沟通svg在前端的一些使用逻辑,让他们给出更规范的svg,这就是本文的背景。
三种图标的引入方式
首先一般第三方组件库都会提供图标组件,比如antd提供了@ant-design/icons
,一般在实际使用中是不够用的,这就需要自定义Icon,目前项目中自定义Icon有三种方式
- 直接
import
图标.svg
文件,然后作为<img>
标签渲染 - svg sprite,通过
svg-sprite-loader
插件,将指定文件夹内的所有.svg
文件组装成一个大的.svg
文件,在使用的时候通过use
指定symbol
- 第三种是笔者正在用的方式,相当于第二种的进阶方式,和
@ant-design/icons
提供的createFromIconfontCN()
类似,通过自建svg治理服务,可以简单的使用团队共享出来的svg资源
大多情况下,同一个图标会有三个状态:normal/hover/disabled,每个状态都会对应一种颜色,假如使用了第一种方案,我们就需要三个不同颜色的图标,而且很难实现在hover的时候,颜色transition的效果。而且假如项目接入了主题色的时候,或者设计师要修改颜色的时候,都会很麻烦
相比之下,第二种和第三种方式均使用了svg sprite的方式,可以通过css控制图标的颜色,那么只需要一个图标文件,就能满足不同颜色的需求,相比之下,这种方案比<img>
的方案更好一些
如何导出svg
为了开发的方便,前端的很多同学会安装sketch,用sketch导出需要的icon很方便
- 设计稿选中图标
- 在选中内容的情况下,sketch右下角点击「设为可导出」选项
- 格式选择「svg」,点击最下方的导出选中项
简单三步,就可以导出svg文件,但是这样并不够
sketch直接导出文件存在的问题
视觉面积不一致
关于视觉面积的问题可以先看看这篇文章Optical Effects in User Interfaces
一般来说,sketch导出图标是按照图标的边界去导出的,但是图片的形态个不一样,造成图标的各个边界的大小也不一样,比如在下面的例子中,设计师为了保持正方形和圆形的视觉面积的一致,会把圆形的直径做的大一些
sketch按照图标的边界导出,最初导出的正方形icon的尺寸是400,圆形的尺寸是450,如果你直接通过<img>
引入icon,在界面的宽度就会是400和450,这样确实可以保持视觉大小和设计稿保持一致,但是图标的位置大概率对不齐了,开发的时候就需要针对这种图标进行特殊处理。
假如设计师想统一调整两个图标大小的时候,比如调整到300,那就很难办了。因为一旦你将两个图标都改成300,那肯定圆的视觉面积较小;正确的做法是将正方形的宽度调整到300,而圆的宽度设置为大约337,相当于手动计算一下对应的尺寸,这也是一个办法。
除了这个问题,还有左右/上下重心的问题,比如三角形图标▶️,它的重心必然是偏左边一些,所以设计图上可能会适当的偏右,这里就不详细解释了。
这个问题的解决方法很简单,将所有的图标放到一个略大一些、统一尺寸的正方形区域内。在使用的时候指定一个统一的宽度就可以了
sketch 导出的 svg 不够「纯」
如果你观察过sketch导出的svg源码,你会发现里面有很多层xml节点,会有一些看不太懂的奇怪的标签和属性,svg代码不「纯」会导致一些问题,比如:
- 体积更大,比如一些2k左右的图,可以优化到500b以内
- 难以自定义颜色,有些图标是通过
形状+填充(fill)
实现的,而有的时候又是线条+描边(stroke)
实现的,而我们若要自定义颜色的话,则需要统一指定fill
来实现 - 一些svg的属性不兼容,或者sketch导出的有问题,可能会导致在浏览器里打开的效果都有问题
如何正确输出svg图标
一般的做法是:
- 通过sketch导出
- 使用Adobe Illustrator(简称“AI”,是Adobe系统公司推出的基于向量的图形制作软件),重新编辑一遍:
- 取消所有的「分组」,删除无关标签
- 将「描边」统一转换为「轮廓」
- 可以将一些形状做一些「合并」等操作
- …
- 一般坐完这些事情,最终得到的svg文件内部只有一个
<path>
标签
- 调整画布到一个统一的正方形区域,如果图标本身很特殊可能不需要
- 导出svg,并手动删除fill属性的颜色,这是为了可以通过css自定义颜色(彩色图标除外)
- 使用svgo命令压缩图标
因为AI有一定的上手成本,可以要求设计师完成前3步,再将svg交付给我们,这里可以参考一下阿里巴巴图标库-绘制规则
图标治理平台
笔者在文章开头的位置,不是提到了搭建了一个图标治理平台吗,治理平台是怎么做的呢?其实和上面的流程一样,前三步也是需要设计师来完成,然后设计师导出svg后直接上传,然后会在后端根据页面的的「是否保留颜色」来控制是否去除fill属性,同时使用svgo进行文件的压缩,完成了这一系列的操作后才会将文件落盘存储
这里画张图简单说一下图标治理平台做了什么事情:
其中下载svg sprite到本地的方式可以参考一下createFromIconfontCN
方法的实践,通过加载一个cdn上的js,在这个js中将svg插入到dom中,在组件中直接使用<use>
即可完成图标的使用
总结
在项目中使用可svg-sprite-loader
或者svgr
来管理本地的图标,封装自定义icon,这几本已经满足日常需求了,假如你想将图标都维护起来的话,肯定还是选择部署私有的在线的图标治理平台,自己封装createFromIconfontCN()
方法,直接使用cdn上的资源,肯定是最方便的。
假如有想交流部署图标库经验的,欢迎在评论区留言