Hypocrite Nush
  1. 1 Hypocrite Nush
  2. 2 One Last You Jen Bird
  3. 3 Life Will Change Lyn
  4. 4 かかってこいよ NakamuraEmi
  5. 5 Time Bomb Veela
  6. 6 Libertus Chen-U
  7. 7 Warcry mpi
  8. 8 Flower Of Life 发热巫女
  9. 9 Last Surprise Lyn
  10. 10 BREAK IN TO BREAK OUT Lyn
2019-09-08 15:22:53

切图仔的自我修养——图标管理

同为程序员,在细分工种下,前端和其他方向的一个最大的区别就是除了写代码之外,还要和视觉层面上的图形打交道,对我来说这也是前端最大的魅力,因为我深知图形之美以及其奥妙之处。不过并不是所有前端都会深入图形领域,但对于所有前端来说有一门图形相关的入门课倒是必修的,那就是图标管理了。

图标发展史

前端经过多年的工程化演进,一些细节技术方案也吃到了这波福利,比如图标管理。虽然一直被调侃切图仔,但现在的前端也已经很少切图了,要了解如何摆脱这个称号的话,还是从那个年代开始谈起吧。

img时代

最早期也就是切图仔时代,网页本身就只是用来展示图片和文本信息的。在后端用模板引擎渲染出html展示文本,同时有一个静态资源文件夹,里面存放着需要的图片,在文本需要的地方直接通过url引用即可。那时也没有对图片更细节的划分,图标不就是更小的图片嘛。所以图标的产出到应用大致要经过以下的步骤

PhotoShop从原始图中切出需要部分 => 扣除单色背景 => 在html中引用

现在回头来看这样的方案当然满是缺点,比如资源请求过多,缩放影响清晰度等等,但直至今日这样的方案依然存在,最大的一个优点就在于简单,灵活。如果整个项目只有少量图标的情况下,也不是不能用。

html拿到资源做展示的方案有两种——img标签加载或者是background属性加载,由此也衍生出了各种hack的图标文字居中方案以及CSS Sprites方案。这些都属于前端入门必知也不是今天的重点就不详细介绍了。

font时代

其实严格来说这并不是一套标准方案,而是前人智慧下利用css字体规则构思出的hack方案。首先我们需要了解,网页中的字体究竟是什么。有兴趣的可以随便通过一件字体软件打开一款字体看看,就可以发现,每个文字本身是由矢量图形构成的,这些矢量图形的产出通常是由设计工具ai,sketch完成。在字体规则中,每个文字都有一个原始文字的unicode到对应字体文字的矢量图形映射,所以在html中我们引入字体文件并声明字体后,不同的文字就可以转化对应字体图形了。

既然有unicode到矢量图形的映射,那么我们规定一些unicode映射到指定的图标的规则,不就形成一套完善的图标方案了吗?这套规则的产物就是自定义字体了。初期会有一些代表性的font库提供给前端使用,作为便捷方案是不错,像bootstrap一样。但有自定义需求的情况还是比较多的,后来就有了自定义font解决方案,比较有代表性的项目就是iconfont

这套方案的好处是明显的,首先就是用到了矢量图形解决了缩放的问题,解决了请求数量的问题,再就是相比于img各种样式实现,有了一套规范来约束。同时又由于本身是字体,各种字体相关的css属性都能应用,灵活性足够高。

缺点就在于字体的局限性,只能渲染为单色或者css支持的渐变色。以及后期维护困难,需要借助外部工具输出相关字体文件,每次更新图标都是挺麻烦的一件事。

svg时代

随着浏览器的演进以及html的发展,svg这样的矢量图像格式不用再经过字体的转化,可以直接使用html标签在浏览器渲染,终于实现了矢量图标的解放,可以更细节的决定其内部构成,由此产生了一系列围绕svg的工程化方案,是目前最流行的方案,也是本文重点,下面就谈谈就具体细节。

SVG图标解决方案

常规流程

在不做任何优化之前,先了解下如今使用svg的常规流程。

  • 产出svg 图标

    首先我们需要有一个svg图标,这一点和font方案是一致的,通常由设计师在AiSketch中制作并导出。常规制作方法会是用path按步骤绘制,但如果你比较熟悉这些设计工具的话也有各种奇技淫巧生产svg,比如imgsvg等。

  • 图标文件夹统一管理

    img类型的图标无异,通常是新建一个icons文件夹,内置各种各样的svg图标。

  • html中使用svg

    到了这一步就应该了解svg相关的html标签使用知识了。除了和img相同的src引用和background引用之外,还可以直接用相关标签<path>等绘制,以及<use>引用。相比于font中的svg,大大拓宽了矢量图形的组合自由度。

  • 优化svg的样式

    利用css的继承特性,在<svg>上的许多css属性设置都可以被内层享受到,除了常规css属性外,还有svg特有的属性,比如fill,stroke等。

工程优化

可以看到常规流程的后两步,都有各种各样的实现。如果是个人项目当然随你喜欢,但在一个大型工程项目中,还是需要有一套统一的管理方案,目前最推荐的方案是SVG Sprites

SVG Sprites

听名字就知道了,这是类似于CSS Sprite的一项将svg整合到一起并按统一规范使用的技术。这个技术核心在于svgsymbol标签。通常一份SVG Sprites是由多份symbol组合而成的,基本结构如下:

<svg>
    <symbol id="icon-a"></symbol>
    <symbol id="icon-b"></symbol>
    <symbol id="icon-c"></symbol>
</svg>

symbol中就是各个图标的具体实现的声明。需要被使用时,会通过<use>xlink:href属性引用到指定symbol,再利用shadow dom渲染到页面。格式如下:

<svg><use xlink:href="path/icons.svg#a"></use></svg>

这样就成功引用到了idasvg 图标。

当然要我们手动将各种图标集成到icons.svg中也是件麻烦事,现在iconfont也提供了SVG Sprites管理和生成功能,生成的icons.svgicons文件夹共同维护即可。

需要注意的一点是,以上这种通过路径引用其他svg文件的方式称作外部SVG Sprites,但由于兼容性的问题,部分浏览器版本不支持外部引用的形式,只支持形如<use xlink:href="#a" />内联引用,可以使用svg4everybody这个工具做polyfill,当浏览器不支持svg外部引用时,其会异步加载svg源文件并注入到页面中,将引用方式改造为内联。

接入Webpack

统一了规范是很好,但相对的整套体系也变得繁重了。想象一下每次需要新增一个图标,不能直接再扔到icons文件夹下了,还需要打开iconfont重新制作icons.svg文件,再复制到项目中,同时还要注意和源文件的同步问题。想想都觉得麻烦,所以还是需要一份自动化的策略。得益于Webpack等繁荣的打包工具生态,通过svg-sprite-loader就能帮助我们完成这件事,大致需要经过如下几个步骤。

  • Webpack配置文件中配置svg-sprite-loader处理.svg后缀文件

详细配置就不细说了,需要注意的一点就是,并不是所有svg文件都是图标,所以最好通过excludeinclude属性分别对不同类型的svg文件处理。

  • 新建聚合所有svg图标的js导出文件

这一步也是常规操作了,将来需要用到icon的地方直接引用该文件即可。由于图标通常很多而且路径都统一在icons文件夹下,可以使用Webpack提供的语法糖require.context实现统一引入。

  • 配置svgo进一步优化svg文件输出

svg-sprite-loader的配置仅提供了有限的优化功能,因为其本职工作还是生成SVG Sprite文件,而svgo是专门为svg优化而生的,支持更多的优化项。

小结

svg图标是未来,但其实也只是svg的一小部分应用而已。其真正强大之处还在于动画方面的应用,当然这又是一个大话题了,之后有计划搞一系列专题文章聊聊。

-- EOF --

添加在分类「 前端开发 」下,并被添加 「CSS」「HTML」「工程化」「性能优化」「Webpack」 标签。