[聚合文章] 基于Vue & SVG 的 icon 解决方案

vue.js 2017-12-27 31 阅读

Icon 解决方案

我们说 Icon 有两种场景.

  • UI 提供 png 格式的图标;
  • UI 提供 SVG, 或者有时候直接是我们自己寻找图标, 比如做一些 CMS 后台的时候.

png 格式的图标就不关心了, 我们说 SVG 的图标.
使用 SVG 比较好一点:
保真, 颜色可以随意改来改去啥啥的

在之前

在之前一般在做 UI 不给图标, 需要自己找图标的项目的时候, 过程是:

  1. 打开 iconfont, 查找需要的图标, 点击 加入购物车按钮.
  2. 把所有 加入购物车 的图标形成一个 项目.
  3. 下载项目
  4. 在自己的项目中引入 iconfont.css, 以及放置下载下来的资源文件.

这种方式在:
需要新增图标的时候, 就蛮麻烦.
然后可能项目 A 使用到了图标 12345, 项目 B 使用到了图标 123. 此时如果项目 B 直接使用
A 项目的图标资源(因为懒啊), 就会导致 45 没有用到但是也加载了.

然后

换一种 SVG 的使用方式, 每次都只下载一个 svg 文件下来, 通过 img src="xx.svg" 的方式引入.
这样方式不能修改 svg 的颜色.

那直接在 html 里面放 svg ? -- 太繁琐.

通过 <use> 的方式引入, 允许我们通过 css 修改颜色, 但是也有问题:

要求我们将所有的 SVG 图标合并成一个文件.
合并是一件事情, 合并之后, 就不能支持: 提前提供1000个图标, 在打包的时候只打包被使用到的.

期望的使用方式

文件目录:
node_modules/wc-svg-icon/

1.svg
2.svg
3.svg
...
index.js
...

引入:
import Icon from 'wc-svg-icon';
Vue.use(Icon);

使用:
<icon name="eye"/>
或者
<icon-eye/>

具体的逻辑:
Icon 组件接受 props= name, 拿到值之后, 通过 require 导入 SVG, 然后将 SVG 解析出来.
然后渲染成 SVG.

require 能不能导入 SVG 的问题.
require 可以不在顶级作用域, 所以不使用 import;
requrie 不支持路径是一个变量, 但是支持拼接字符串. 所以可以这样:
require(./assets/${comment}.svg);

  • 使用 SVG-url-loader 会返回一串字符串, 然后头上面还有一些 data/image 这样的东西;
  • 使用 xml-loader

这个返回一个对象回来:

{
    "SVG": {
        "$": {
            "t": "1514361557076",
            "class": "icon",
            "style": "",
            "viewBox": "0 0 1227 1024",
            "version": "1.1",
            "xmlns": "http://www.w3.org/2000/SVG",
            "p-id": "11009",
            "xmlns:xlink": "http://www.w3.org/1999/xlink",
            "width": "153.375",
            "height": "128"
        },
        "defs": [{
            "style": [{
                "$": {
                    "type": "text/css"
                }
            }]
        }],
        "path": [{
            "$": {
                "d": "M949.590199 1023.567385l-114.4267-165.691593L95.607943 857.875792C42.828897 857.875792 0 815.046895 0 762.26785L0 95.607943C0 42.828897 42.828897 0 95.607943 0l1035.247993 0c52.562738 0 95.607943 42.828897 95.607943 95.607943l0 666.876215c0 52.779045-42.828897 95.607943-95.607943 95.607943l-61.431348 0L949.590199 1023.567385zM95.607943 65.757499c-16.439375 0-29.850444 13.411069-29.850444 29.850444l0 666.876215c0 16.439375 13.411069 29.850444 29.850444 29.850444l774.164766 0 81.115336 117.455006 85.008872-117.455006 94.95902 0c16.439375 0 29.850444-13.411069 29.850444-29.850444L1160.706379 95.607943c0-16.439375-13.411069-29.850444-29.850444-29.850444L95.607943 65.757499z",
                "p-id": "11010"
            }
        }]
    }
}

将返回的对象, 赋值给 data 里面的某个字段. 可行.

用对象的所有参数字段来给 SVG 赋值.

这块直接使用 vue-svg-icon 提供的包, 哎可以啊. 不错不错.

wc-svg-icon

基于 Vue & SVG 的 icon 解决方案

感谢

vue-svg-icon
项目中对 SVG 进行解析的代码, 直接从上面的项目中拿过来用的, 感谢.

Font-Awesome
动画效果来自于它.

Install

npm i wc-svg-icon --save-dev

// main.js
import Icon from 'wc-svg-icon';
import 'wc-svg-icon/style.css';
Vue.use(Icon);

备注: style.css 不强制要求引入, 不引入也可以正常运行, 只是 animation 参数无效.

Usage

<icon name="xxxx"/>

这里的 'xxxx' 是你给定的 SVG 图标的名称. 比如说你现在有 10 个 SVG 图标, 你需要做的事情是:
1. 在 node_modules 里面找到 wc-svg-icon 目录
2. 把这 10个图标, 拷贝到 wc-svg-icon 目录中.

Config

icon 组件接受以下 props 配置选项:

name:    图标的名称, 需要和 SVG 名相同, 不需要带路径.比如:
<icon name="hello"/>

fill:    SVG 图标的 fill 颜色, 默认会使用 SVG 原本的颜色, 如果你传递了 fill 属性, 则会使用你所传递的.比如:
<icon name="hello" fill="red"/> // 此时图标会呈现 red 色. 

height:    控制 SVG 图标的高度
width:    控制 SVG 图标的宽度

当然你也可以通过为 <icon> 添加 class 的方式来设置 SVG 的样式. 
<icon class="foo"/>
之所以把 fill, height, width 单独提出来是因为这些对我而言经常用到.

animation:    设置图标的动画效果, 比如:
<icon animation="rotate"/>
... 当前只支持一种效果, 就是 rotate(旋转).
其实这个玩意有点鸡肋, 建议如果需要 animation 效果的同学, 可以直接自己写 animation 或者引入 animate.css
然后这样:
<icon class="animated bounce"/>

一些问题

后续会不断的添加一些默认的 SVG icon, 由于打包的时候没有引入的icon 不会打包进项目, 所以icon的个数
不会影响到打包的体积大小.

如果你是希望将本项目直接拷贝到自己的项目中使用

  • 拷贝 src/wc-svg-icon 目录
  • 安装 xml-loader 依赖:
npm i xml-loader --save-dev
  • 所有的图标放在 wc-svg-icon/icons 下即可.

下一步

  • 希望支持 Font Awesome.
  • 目前 icon 只能放在 node_modules/wc-svg-icon 目录下面, 不支持自定义路径.(如果有知道更好的方式的同学, 还请不吝赐教)

项目地址

wc-svg-icon

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。