使用 SVG 图标: (1) 编写 Icon 组件

SVG 便可缩放矢量图形。跟普通的图片相比,它放大也不会失真,而且文件体积更小。如今浏览器对 SVG 支持性是很是好的,咱们常常在项目中使用它,好比使用 SVG 图标或者使用 SVG 图片解决高清屏幕下的 1px 显示问题css

本文将主要谈论 SVG 图标的使用,而且会结合实例给出相应的解决方案。文章将分为上下两篇: 上篇,主要介绍 SVG 的相关知识,介绍如何使用 gulp 合并图标,并编写一个 Icon 组件。下篇中,将介绍如何编写 webpack 插件来处理 SVG 文件。html

1. SVG 图标

使用 SVG 作图标的话,就不得不拿来与 iconfont 作比较。iconfont 的兼容性比较好,但在显示效果上并不如 SVG,而且不支持多色图标。因此如今是推荐使用 SVG 图标vue

在项目中使用 SVG 图标有多种方式,其中一种是 SVG Sprite,即把各个图标合并成一张背景图片。但这种方式很是不灵活,好比咱们没法调整某个图标的大小或者颜色。webpack

相比之下,一种更好的方式使用 SVG Symbol。把个个图标合并成一个包含多个 symbol 的 SVG 文件。在须要使用图标的地方,引用对应的 symbol 便可。git

假设有下面这一段 symbol 文件,里面包含了一个 id 为 QQ 的图标。github

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <symbol id="QQ" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
    <path d="M2.87 23c-1.42 3.49-1.67 6.78-.54 7.37.79.44 2.06-.54 3.24-2.31a9.73 9.73 0 0 0 3.24 5.11C7.09 33.82 6 34.9 6 36.08c0 2 3 3.58 6.78 3.58 3.39 0 6.19-1.28 6.73-3h.79c.54 1.72 3.34 3 6.73 3 3.78 0 6.78-1.57 6.78-3.58 0-1.18-1.13-2.26-2.85-2.9a9.73 9.73 0 0 0 3.24-5.11c1.18 1.77 2.41 2.75 3.24 2.31 1.18-.59.93-3.93-.54-7.37-1.13-2.7-2.65-4.71-3.83-5.16v-.54a5.32 5.32 0 0 0-.79-2.8v-.2A2.92 2.92 0 0 0 32 13C31.69 5.93 27.18.33 19.86.33S8 5.93 7.73 13a2.92 2.92 0 0 0-.29 1.33v.2a5.32 5.32 0 0 0-.79 2.8v.54C5.57 18.31 4 20.27 2.87 23z"/>
  </symbol>
 </svg>
复制代码

如今要使用这个图标,经过设置 id 就能够引入对应的 symbol。web

<svg class="icon icon-QQ">
  <use xlink:href="#QQ"></use>
</svg>
复制代码

咱们给图标添加了一个类名,若有必要,还能够经过 CSS 就能够来调整图标的样式。这种方式可控性强,而且显示效果也好。gulp

2. gulp-svg-sprite 的使用

设计师给咱们的图标都是一张张图片,差很少像下图这样。浏览器

icon 文件夹

接下来须要对 SVG 进行合并压缩处理。最省事的方式是使用 阿里巴巴矢量图标库 去管理图标,须要使用 symbol 文件的话,在页面上引入脚本便可。若是你喜欢这种方式,那下文就能够没必要再看了😂。app

在这里,咱们使用 gulp 以及 gulp-svg-sprite 来处理 SVG 图标。gulp-svg-sprite 是一个专门用来处理 SVG 图片的 gulp 插件,提供了生成 sprite 背景图片与 symbol 文件的功能。下面是 gulp 的配置文件

const gulp = require('gulp')
const svgSprite = require('gulp-svg-sprite')
const config = {
  // 去除 svg icon 颜色
  svg: {
    transform: [
      function (svg) {
        return svg.replace(/(<style.*?<\/style>)/g, '').replace(/(fill=\"#([0-9a-f]{6})\")/g, '')
      }
    ]
  },
  mode: {
    view: {
      bust: false,
      sprite: 'sprite.svg',
      render: {
        css: true
      }
    },
    symbol: true
  }
}

gulp.task('svgSprite', function () {
  return gulp.src('./icon/*.svg').pipe(svgSprite(config)).pipe(gulp.dest('svg'))
})

gulp.task('default', ['svgSprite'])
复制代码

经过设置 mode 来配置生成不一样类型的文件。上述配置中,咱们选择生成 spirite 背景图片与 symbol 文件。有些 SVG icon 中预设的有些颜色,在合并成 symbol 文件前,要作去色处理。配置插件的 transform 函数,便可完成对去色。

在项目文件夹目录下执行 gulp 命令,生成的文件以下。

svg文件夹

接下来拷贝 sprite.symbol.svg 的内容拷贝到 index.html 中,而且设置 SVG 元素隐藏。以后 Icon 组件就可使用了。这一步操做是手动进行的,很是不方便,因此在下篇中,咱们经过开发 webpack 插件来自动插入 symbol 文件内容到 index.html 中。

<!-- index.html -->
<body>
    <!-- 拷贝 symbol 文件到这里 -->
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
        <symbol id="QQ">
        <!-- .... -->
        </symbol>
    </svg>
    <div id="app"></div>
</body>
复制代码

3. Vue Icon 组件的实现

如今开发的 Icon 组件提供哪些功能或者有哪些参数呢?暂时提出如下几点需求:

  1. 设置 type 值指定要用的图标
  2. 能够定制图标的尺寸
  3. 能够设置图标的颜色

一个示例以下:

<template>
  <svg :class="iconClassName" :style="{color: this.color}">
    <use :xlink:href="'#' + type"></use>
  </svg>
</template>
<script>
export default {
  name: 'icon',
  computed: {
    iconClassName () {
      return ['icon', `icon-${this.size}`, `icon-${this.type}`]
    }
  },
  props: {
    type: {
      required: true,
      type: String,
      validator (value) {
        return ['wechat', 'QQ', 'weibo'].indexOf(value) !== -1
      }
    },
    size: {
      type: String,
      default: 'medium',
      validator (value) {
        return ['small', 'medium', 'large'].indexOf(value) !== -1
      }
    },
    color: {
      type: String,
      default: '#cccccc'
    }
  }
}
</script>
<style lang="scss">
.icon {
  display: inline-block;
  vertical-align: middle;
  fill: currentColor;
  &.icon-medium {
    width: 24px;
    height: 24px;
  }
  // ...
}
</style>
复制代码

Icon 组件有三种大小的尺寸,默认状况下是 medium。图标颜色能够根据自定义,默认是 #cccccc。在合并 SVG 图标时,去除了图标自己的颜色。设置 Icon 的样式规则中有这一条 fill: currentColor;,这段属性代表 SVG 路径填充色继承当前元素的颜色,这样咱们就能够定制图标的颜色了。

针对 Icon 组件的两个props: type 与 size,编写了 validator 函数来校验传入 prop 值,当传入的 prop 值非法时,开发环境下会有错误的提示,从而避免了 Icon 组件使用不正确的问题。

组件注册后,就能够直接使用了。

<icon type="QQ" />
复制代码

完整的代码点击这里

4. 总结

在本篇文章,咱们完成了 SVG 图标的合并与 Icon 组件的编写。SVG 图标由于其自身的优点与浏览器的良好支持,很是适合在项目中使用。但愿你们能够探索出更多的用法。

下篇文章中,咱们将经过开发 webpack 插件,避免手动的复制粘贴 SVG symbols 文件。

参考资料

相关文章
相关标签/搜索