# svg-sprite-loader的使用

svg-sprite-loader 将加载的 svg 图片拼接成 雪碧图,放到页面中,其它地方通过 <use> 复用

# 安装和配置 svg-sprite-loader

安装:

npm i -D svg-sprite-loader

webpack(vue.config.js) 配置:

 chainWebpack: config => {
    config.module
      .rule("svg")
      .exclude.add(resolve("src/icons/svg"))
      .end()
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]"
      })
      .end()
  }

WARNING

一般情况下都会有配置 url-loader,注意urlloader 中要将 icons 文件夹排除, 不让 url-loader 处理该文件夹

关键字:exclude: [resolve('src/icons')]

# 准备工作

在 src 下建立以下目录和文件:

src

components

svg-icon.vue

icons

svg

eye.svg

index.js

utils

validate.js

上述eye.svg就是存放svg图标,如果要新增图标,可在svg文件夹下新建文件

打开阿里云图标官网点击前往 (opens new window)

搜索眼睛

搜索一个眼睛图标, 找到想要的图标,鼠标悬浮时点击下载按钮。弹出如下图所示

下载svg代码

点击下载svg代码,并放在eye.svg文件上。

eye.svg文件如下

<svg t="1651040485477" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2294" width="200" height="200"><path d="M512 832c-156.448 0-296.021333-98.730667-418.410667-291.605333a52.938667 52.938667 0 0 1 0-56.789334C215.978667 290.730667 355.552 192 512 192c156.448 0 296.021333 98.730667 418.410667 291.605333a52.938667 52.938667 0 0 1 0 56.789334C808.021333 733.269333 668.448 832 512 832z m0-576c-129.514667 0-249.461333 83.850667-360.117333 256C262.538667 684.149333 382.485333 768 512 768c129.514667 0 249.461333-83.850667 360.117333-256C761.461333 339.850667 641.514667 256 512 256z m0 405.333333c-83.210667 0-150.666667-66.858667-150.666667-149.333333S428.789333 362.666667 512 362.666667s150.666667 66.858667 150.666667 149.333333S595.210667 661.333333 512 661.333333z m0-64c47.552 0 86.101333-38.208 86.101333-85.333333S559.552 426.666667 512 426.666667c-47.552 0-86.101333 38.208-86.101333 85.333333s38.549333 85.333333 86.101333 85.333333z" p-id="2295"></path></svg>

在components文件夹下的svg-icon.vue中粘贴以下代码

<template>
  <div v-if="isExternal" :style="styleExternalIcon" :class="svgClass" v-on="$listeners" />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
import { isExternal } from "@/utils/validate"
export default {
  name: "SvgIcon",
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String,
      default: ""
    }
  },
  computed: {
    isExternal() {
      return isExternal(this.iconClass)
    },
    iconName() {
      return `#icon-${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return "svg-icon " + (this.isExternal ? "svg-external-icon " : "") + this.className
      } else {
        return "svg-icon " + (this.isExternal ? "svg-external-icon " : "")
      }
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        "-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`
      }
    }
  }
}
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
.svg-external-icon {
  background-color: currentColor;
  mask-size: cover !important;
  display: inline-block;
}

.svg-icon.svg-animation,
.svg-external-icon.svg-animation {
  animation: rotate 2s linear infinite;
}
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>

在icons文件夹下的index文件粘贴以下代码

import Vue from 'vue'
import SvgIcon from '@/components/svg-icon'// svg组件

// register globally
Vue.component('svg-icon', SvgIcon)

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

utils/validate.js

/**
 * describe 判断是否是链接
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

最后在main.js中引入

import "@/icons"  //此处使用@ 默认已配置了别名设置

接下来就可以使用svg图标了

# 使用方法

demo如下

  <div class="login">
    登录
    <svg-icon className="svg-icon-eye" icon-class="eye"></svg-icon>
  </div>

页面展示如下

svg图标还用效果

使用className 来定义类名 使用 icon-class 区分使用哪个svg图标

可通过配置color属性修改svg图标颜色

  <div class="login">
    登录
    <svg-icon className="svg-icon-eye" icon-class="eye"></svg-icon>
  </div>
  
<style scoped>
.svg-icon-eye{
	color: red;
}
</style>

展示效果如下 svg图标还用效果

至此svg图标就可以使用了

也可以像img标签一样使用外部链接

<svg-icon className="svg-icon-eye" icon-class="http://www.xiaobusoft.com/static/svg-test.svg"></svg-icon>

如果想要让图标旋转,仅需添加 svg-animation 类即可

 <svg-icon className="svg-icon-eye svg-animation" icon-class="http://www.xiaobusoft.com/static/svg-test.svg"></svg-icon>

# 无法改变svg图标颜色

​ 上述配置完成后,可以正常使用svg图标,但是有时候UI设计师给的svg图标或者在icon-font网站上下载的svg图片,我们颜色使用CSS配置了,但是就是不会改变。

# 方法一

查阅svg资料发现,svg代码中的fill属性对其填充了颜色,且优先级最高。因此只要手动删除掉 fill属性值即可。显然这是一个非常笨的方法

# 方法二

使用svgo-loader

查阅svg相关资料,发现svg颜色无法更改,原因是svg代码中的fill属性对其填充了颜色,且优先级最高。一次姑妈,i

安装svgo-loader

npm i -D svgo-loader

深化vue.config.js配置

chainWebpack: config => {
    config.module
      .rule("svg")
      .exclude.add(resolve("src/icons/svg"))
      .end()
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]"
      })
      .end()
      .before("svg-sprite-loader")
      .use("svgo-loader")
      .loader("svgo-loader")
      .options({
        plugins: [
          {
            name: "removeAttrs",
            params: {
              attrs: "fill"
            }
          }
        ]
      })
      .end()
  }

此时配置的CSS颜色,就能生效了。

它会去掉svg原有的颜色,默认为黑色。

此插件的大概意思就是帮助去除svg代码里面的fill属性

此插件不会对文件进行更改,仅运行时或者打包时生效

# 方法三

使用svgo 插件,与方法二插件差不多,用法不一致。原理也是清除svg代码里面的属性。

安装svgo

npm install svgo@1.2.2

DANGER

使用svgo时需要注意版本,2.0以前支持yml配置文件,2.0以后不再支持yml,只支持js配置文件,并新增了extendDefaultPlugins方法

在icons文件夹下新建svgo.yml文件

内容大致如下

# replace default config

# multipass: true
# full: true

plugins:

  # - name
  #
  # or:
  # - name: false
  # - name: true
  #
  # or:
  # - name:
  #     param1: 1
  #     param2: 2

- removeAttrs:
    attrs:
      - 'fill'
      - 'fill-rule'

配置package.json文件

  "scripts": {
    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
  },

执行命令去除多余属性

npm run svgo

这时候就会对 src/icons/svg 文件夹下的文件执行去除响应配置的属性操作,此操作会对文件进行修改。

其他目的

我们很多网上下载或者 Sketch 导出的 svg 会有很多冗余无用的信息,大大的增加了 svg 的尺寸,我们可以使用 svgo 对它进行优化。比如下图是用 Sketch 导出的一个 svg

img

img

img

无用的信息都被处理掉了。

更多详细的配置 可以在 /src/icons/svgo.yml中进行配置。

# 总结

​ 以上就是vue项目使用svg图标的详细内容。上述修改方法三选一。随意使用,比较懒的可以使用方法二。

阅读原文 (opens new window)