介绍
目前我们实现css图标主要是通过svg实现,svg图标相比于图片图标有以下优点:
- SVG是矢量图形文件,无限放大不失真,显示清晰, 可以适应不同的尺寸和分辨率。
- 可以用CSS样式来自由定义图标颜色,比如颜色/尺寸等效果。
- 使用SMIL、CSS或者是javascript可以制作充满灵性的交互动画和滤镜效果。
- 由于SVG也是一种XML节点的文件,所以可以使用gzip的方式把文件压缩到很小
svg雪碧图
SVG Sprite 类似于CSS中的Sprite技术。将图标图形整合在一起,实际呈现的时候准确显示特定图标。svg实现雪碧图主要是靠和标签
symbol和use
symbol元素用来定义一个图形模板对象。symbol元素本身是不显示的,只有使用元素引用后才会进行渲染。
定义了元素之后,可以使用元素来对它进行无限次实例化展示。通过定义元素xlink:href属性来指定要展示的图标,xlink:href属性值为要展示元素的id。
例子如下:
<svg>
<!-- symbol definition NEVER draw -->
<symbol id="sym01" viewBox="0 0 150 110">
<circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red"/>
<circle cx="90" cy="60" r="40" stroke-width="8" stroke="green" fill="white"/>
</symbol>
<!-- actual drawing by "use" element -->
<use xlink:href="#sym01"
x="0" y="0" width="100" height="50"/>
<use xlink:href="#sym01"
x="0" y="50" width="75" height="38"/>
<use xlink:href="#sym01"
x="0" y="100" width="50" height="25"/>
</svg>
将上述代码放入到html中没有使用元素引用时,页面是空白的,使用元素引用之后效果如下:
使用
svg-sprite-loader生成svg雪碧图
svg-sprite-loader是用来生成svg 雪碧图的webpack loader, 它可以把所有引入的svg文件自动生成symbol标签,在需要使用图标的地方使用元素引用就可以了
使用步骤:
- 安装svg-sprite-loader
npm install svg-sprite-loader -D
或 yarn add svg-sprite-loader -D
- 配置webpack loader
{
test: /.svg$/,
loader: 'svg-sprite-loader',
include:
options: {
symbolId: '[name]' // 使用文件名作为symbolId
}
}
在vue-cli3中的配置方式
config.module
.rule('svg-sprite')
.test(/icons/.+(.svg)(?.*)?$/)
.use('svg-sprite')
.loader('svg-sprite-loader')
.options({
symbolId: '[name]'
})
创建一个公用的icon组件
- 创建icon组件
<template>
<svg class="icon" :width="size" :height="size">
<use :xlink:href="iconName" />
</svg>
</template>
export default {
name: 'ICON',
props: {
name: {
type: String,
required: true
},
size: {
type: Number,
default: 16
}
},
computed: {
iconName() {
return `#${this.name}`
}
}
}
</script>
使用
import Icon from 'com/icon/index.vue'
import './close.svg'
<icon name="close"/>
- 引入所有的svg文件
在每次使用一个图标的时候import 一个svg文件是非常麻烦的事情, 我们可以通过webpack的require.context 生成context module 动态引入icon,这样每次添加一个svg文件时就不用手动添加该svg的import了
require.context接受3个参数:1.文件夹 2.是否使用子文件 3.文件匹配的正则
require.context会返回一个函数,该函数有keys,id,resolve()属性
- keys()方法返回的该模块可以处理的模块的数组,就是满足该参数的模块, 类似于['./close.svg', './open.svg']
- resolve()返回请求的module的id
- id是该context module的id
require.context(directory, useSubdirectories = false, regExp = /^.///)
// requires and returns all modules that match
const requireAll = requireContext => requireContext.keys().map(requireContext);
// import all svg
const req = require.context('./assets/svg', true, /.svg$/);
requireAll(req);
- 全局注册ICON组件
入口文件index.js
import Icon from 'com/icon/index.vue'
Vue.component('Icon', Icon)
- 在自己的组件中使用
<icon name="close" size="12" />