svg是什么
SVG是一种基于XML的矢量图形格式,可以任意缩放大小不失真。用于在Web和其他环境中显示各种图形;它允许我们编写可缩放的二维图形,并可通过CSS或JavaScript进行操作。
使用方法
一、直接使用
当成img图src导入, src=“1.svg”
缺点:多发一次请求
<!-- 精灵图----- -->
<div>
<img src="../../assets/svg/eye.svg" alt="">
</div>
二、以svg标签的形式使用
好处:节约请求
缺点:页面结构不清晰,一旦svg图片稍大,占用很大的html结构空间
- 先svg包symbol元件,生成svg精灵图
- 页面svg利用use 通过 id 使用精灵图中的小图
<!-- 1.声明精灵图 -->
<svg style="display:none;">
<!-- 2.svg标签改成symbol 就变为了精灵图的一个元件 在元件上声明id属性 -->
<symbol id="one" width="400" height="400">
<path d="M 50 50 H 150" stroke="blue" stroke-width="5" fill="none" />
</symbol>
<symbol id="two" width="150" height="150">
<path d="M80 80 A45 45, 0, 0, 0, 125 125" />
</symbol>
</svg>
<!-- 3.根据id调用精灵图中的svg -->
<svg>
<use xlink:href="#one" ></use>
</svg>
<svg>
<use xlink:href="#two" ></use>
</svg>
三、优化写法
使用webpack的工具
- 用require.context方法将当前目录下所有svg文件读取到内存中;
- 使用svg-sprite-loader 或 iconfont js 包, 快速生成 svg精灵图;
- 封装svg-icon组件, 快速使用 svg 精灵图;
- 页面中直接使用
<svg-icon icon-class="svg文件名" />
步骤:
- 下载插件:
yarn add svg-sprite-loader 或则 npm i svg-sprite-loader
- 新建icons文件夹,icons文件夹放入所有的svg文件夹和index.js,在index.js文件中用require.context方法将当前目录下所有svg文件读取到内存中。
// 导入组件对象
import SvgIcon from '@/components/SvgIcon'// svg component
// 1.注册全局组件
Vue.component('svg-icon', SvgIcon)
// 2.引入目录所有的svg,将svg中的文件生成精灵图
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
3.生成svg精灵图,在vue.config.js文件,利用svg-sprite-loader插件打包SVG,生成一张大的svg精灵图,根据id取用图片:
// set svg-sprite-loader
// 1. 会把导入的所有的svg文件转化成一个个symbol标签
// 2. 给每一个symbol标签绑定id, id的名称: icon-[svg文件名]
// 3. 会把所有的symbol标签放到一个大的svg标签中, 从而形成svg精灵图
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.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()
- 封装svg-icon组件, 快速使用 svg 精灵图
创建src/components/SvgIcon/index.vue文件,
v-on=“$listeners” 批量注册事件
将 xlink:href 封装到组件内, 使用起来更方便
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" 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.className
} else {
return 'svg-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;
}
</style>
组件中引入utils/validate.js
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
- main.js中全局引用icon文件夹里的字体图标
import '@/icons'
- 页面中直接使用
<svg-icon icon-class="svg文件名" />