前端SVG-icon实践


Part.1 为什么是SVG?

在网页中实现icon的方式,主要以字体图标SVG为主

纵向对比字体图标SVG 如下:

字体图标SVG
清晰度浏览器会认为字体图标是一种字体,所以显示的图标是会有一些锯齿,并不是完全的平滑锐利完全的矢量图形,线条平滑锐利。
css控制你可以通过font-size来控制字体图标的大小。还可以使用color来改变颜色,还可以使用CSS来为它添加阴影和使它旋转等等。SVG图标可以实现CSS对字体图标控制的全部功能。并且可以表现得更好,因为你可以控制整个SVG图标得某一个部分,你还可以使用SVG独有的CSS控制,如stroke属性等。
易用性如果使用一个创建好的字体图标库(如Font Awesome)显得有点冗余,你使用到的图标只是很少很少的一部分。SVG图标使用非常简单,你可以完全手动处理。也可以使用IcoMoon来创建。或者使用一些辅助工具
兼容性广泛支持,包括IE6。IE8以下以及Android 2.3以下的浏览器不支持SVG图标。

详细对比可以参照: 在网页中使用内联SVG图标和字体图标的比较

所以,综上所述,在不考虑兼容IE8以下浏览器的浏览器的情况下,SVG无疑在各方面都是一个更好的选择

Part. 2 怎样使用SVG?

使用SVG实现icon,SVG-Sprite是必不可少的

如张鑫旭大大的一篇文章所言:未来必热:SVG Sprite技术介绍

SVG-Sprite的最佳实践是使用symbol元素

我们使用iconfont的代码应用为示例,通过symbol元素的方式实现icon:

首先引入iconfont提供的图标库:

<script src="http://at.alicdn.com/t/font_8d5l8fzk5b87iudi.js"></script>

然后给icon加上通用的样式:

<style type="text/css">
    .icon {
       width: 1em; height: 1em;
       vertical-align: -0.15em;
       fill: currentColor;
       overflow: hidden;
    }
</style>

挑选一个图标引入页面:

<svg class="icon" aria-hidden="true">
    <use xlink:href="#icon-tuichu"></use>
</svg>

Part.3 在Vue中使用SVG

为了让svg icon更加方便调用,我们可以抽象一个组件:

<template>
  <svg class="svg-icon" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>

<script>
export default {
  props: {
    iconClass: {
      type: String,
      required: true
    }
  },
  computed: {
    iconName() {
      return `#icon-${this.iconClass}`
    }
  }
}
</script>

<style>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

通过组件,当我们想要在项目中使用icon的时候,只需要调用组件,并且传入指定icon的类名就可以了

<svg-icon icon-class="tuichu"></svg-icon>

Part.4 引入自定义的SVG

以上我们使用的都是iconfont为我们制作好的SVG-Sprite,想把我们自己的SVG文件制作成SVG-Sprite还需要一个插件:svg-sprite-loader

安装svg-sprite-loader:

npm install svg-sprite-loader -D

修改webpack配置:

 {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [resolve('src/icons')],
        options: {
          // 根据svg文件名给每个symbol添加一个指定id,用于调用icon
          symbolId: 'icon-[name]'
        }
 },
 {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        exclude: [resolve('src/icons')],
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
 }

值得注意的是

我们不需要svg-sprite-loader去处理项目中所有的svg文件

所以我们把想要做成sprite的svg文件统一存放在src/icons目录下

然后使用webpack的include配置来指定svg-sprite-loader只处理这个目录下的svg文件足矣

同理,我们不需要url-loader来处理这个目录下的文件

所以配置exclude选项来让url-loader仅处理这个目录以外的svg文件

然后,通过代码将icons目录下的所有icon引入项目:

const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./icons', false, /\.svg$/)
requireAll(req)

至此,我们就可以将我们要使用的icon放入icons目录,通过调用svg-icon组件,然后传入文件名调用icon


相关链接:
手摸手,带你优雅的使用 icon
完整代码

声明:Mragon|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 前端SVG-icon实践


Carpe Diem and Do what I like