SVG
简单理解svg
SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
SVG 用于定义用于网络的基于矢量的图形
SVG 使用 XML 格式定义图形
SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失
SVG 是万维网联盟的标准
简单理解svg图标
一、Sprite技术
这里所说的Sprite技术,没错,类似于CSS中的Sprite技术。图标图形整合在一起,实际呈现的时候准确显示特定图标。
2.SVG Sprites与symbol元素
目前,SVG Sprite最佳实践是使用symbol元素。symbol元素是什么呢?单纯翻译的话,是“符号”的意思。然,这个释义并不符合这里的场景。不知大家有没有用过Flash,symbol实际上就类似于Flash中的“影片剪辑”、或者“元件”。
因此,我个人觉得,symbol应该解释为“元件”最为恰当!
那,symbol和SVG Sprite又有什么关系呢?
我们可以把SVG元素看成一个舞台,而symbol则是舞台上一个一个组装好的元件,这这些一个一个的元件就是我们即将使用的一个一个SVG图标。
于是,对于一个集合了三个SVG图标的SVG元素的代码结构会是这样:
<svg>
<symbol>
<!-- 第1个图标路径形状之类代码 -->
</symbol>
<symbol>
<!-- 第2个图标路径形状之类代码 -->
</symbol>
<symbol>
<!-- 第3个图标路径形状之类代码 -->
</symbol>
</svg>
每一个symbol就是一个图标元件,但是,只有上面的代码,是无法呈现类似下面的效果的:
因为,舞台上只是放置了图标,如果你不使用(use),是看不见的。就好比你女朋友买了几箱的衣服放家里,如果不穿出去,谁知道她这么土豪呢?
因此,还差一个“使用”,也就是SVG中的
三、SVG中的use元素
use元素是SVG中非常强大,非常重要的一个元素,尤其在Web开发中,为何?
两点:
可重复调用;
跨SVG调用;
1. 可重复调用
你好不容易,用了几十个坐标值,好不容易绘制了一个图形,如果你想再弄一个同样造型,但位置不同的图形出来,你会怎么办?——再复制一遍代码?别说笑了,(如果真那样)SVG文件的尺寸赶得上二师兄的腰围了。
使用
<svg>
<defs>
<g id="shape">
<rect x="0" y="0" width="50" height="50" />
<circle cx="0" cy="0" r="50" />
</g>
</defs>
<use xlink:href="#shape" x="50" y="50" />
<use xlink:href="#shape" x="200" y="50" />
</svg>
结果是(IE9+浏览器和现代浏览器可见):
首先,注意到没有,use元素是通过xlink:href属性,寻找要使用的元素的。#shape对应的就是id为shape的元素。use元素可以有自己的坐标,以及支持transform变换,甚至可以use其他use元素。
这里,两个use元素使用的是同一个g元素(组合),从而实现了图形的重复调用功能。
2. 跨SVG调用
SVG中的use元素可以调用其他SVG文件的元素,只要在一个文档中。
结果仍是那个图形:
而这个跨SVG调用就是“SVG Sprite技术”的核心所在。
试想下,我们只要在页面某处载入一个充满Sprite(symbol)的SVG文件(或直接include SVG代码),于是,在页面的任何角落,只要想使用这个图标,只要简单这一点代码就可以了:
<svg class="size"><use xlink:href="#target" /></svg>
图标尺寸CSS控制,里面只有一个仅有xlink:href属性的use元素,Done! 完成!
这部分内容来自:
https://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/?shrink=1
优缺点比较
1.为什么使用svg-sprite-loader?
通常我们项目都是使用iconfont阿里巴巴图标矢量库,缺点:
操作繁琐,每次ui需要加一些新的图标的时候,都要重新下载图标库的项目,然后把整体的文件(其中包括css,svg,ttf,woff等)替换掉。
如果更改名称的话,需要在图标库里改一次,然后进行下载复制拷贝。
iconfont网站库图标内容有限,特殊业务条件需要uimm们自己设计的图(PSD小图标变身SVG Sprites/font-face历险记)
svg优点:
图标易于实时修改
图标可以带动画
可以使用标砖的prop和默认值来将图标保持在一个典型的尺寸并随时按需改变他们
图标是内联的,所以不需要额外的HTTP请求
可以动态地使得图标可访问
这部分来自:
https://blog.csdn.net/maggie_live/article/details/90169182?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
vue cli3 项目使用svg步骤(想直接配置的看这里就好)
我们可以直接在 iconfont 复制 svg 到项目用就行,但是如果要用很多,那就很不明智了,所以下面方式配置成组件使用方式,方便,有效…
1.安装依赖(现在版本 ^5.0.0)
npm install svg-sprite-loader -D
2.在vue.config.js配置文件中增加svg的配置
注意,这个文件的配置,网上有两种配置方法,我自己配置时都试过了,一种不行, 我现在也不知道为什么不行,就是图标显示不出来,没有报错,把svg-sprite-loader 版本降低到 3.8.0 也不行,嗯嗯嗯…我现在用第二种配置,具体如下:
第一种配置:
这个我配置不行,有知道原因的分享交流
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack(config) {
//排除icons目录中svg文件处理
config.module
.rule('svg')
.exclude.add(resolve('src/icons')) // 这里是svg文件目录,后面会讲到
.end();
//设置svg-sprite-loader处理icons目录中的svg
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()
}
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
}
第二种:
一些说明:
vue-cli3 默认会通过 file-loader 对 .svg 文件进行处理,这里我们并不想让它处理我们的 .svg 图标文件,但是有的 .svg 文件又确确实实需要用它处理(总不可能所有的 svg 文件都用来做图标吧),所以我们要排除掉 file-loader 对 src/icons/svg 这个文件夹的处理
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack(config) {
const svgRule = config.module.rule('svg');
// 清除已有的所有 loader。
// 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
svgRule.uses.clear();
svgRule
.test(/\.svg$/)
.include.add(path.resolve(__dirname, './src/icons/svg')) // 文件目录
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
});
// 修改file对svg的处理,不让它处理
const fileRule = config.module.rule('file');
fileRule.uses.clear();
fileRule
.test(/\.svg$/)
.exclude.add(path.resolve(__dirname, './src/icons/svg'))
.end()
.use('file-loader')
.loader('file-loader');
// 修改images loader 添加svg处理,这个可以不添加,我看到有的有加
// const imagesRule = config.module.rule('images')
// imagesRule.exclude.add(resolve('src/icons'))
// config.module
// .rule('images')
// .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
}
}
3. 在 components 中创建 SvgIcon 组件
组件内容:
<template
<!-- class绑定类名 -->
<svg :class="svgClass" aria-hidden="true">
<!-- use绑定id -->
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'svg-icon',
props: {
// 使用时 图标对应的文件名
iconClass: {
type: String,
required: true
},
//图标类名,通过这个属性自定义类名,方便修改图标大小,颜色
className: {
type: String
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
/* 默认样式设置 默认宽高1em*/
width: 1em;
height: 1em;
vertical-align: -0.15em;
/* 当前颜色 */
fill: currentColor;
overflow: hidden;
}
</style>
4. 在 src 目录下创建 icons文件夹, icons/svg 用来放 svg文件, icons/index.js 写相关js
(1) svg文件放我们从阿里 iconfont 下载下来的svg文件
(2) index.js 文件如下
这里是全局注册组件
因为可能很多地方都会用到图标,这里选择全局注册 SvgIcon.vue 组件
import Vue from 'vue'
import svgIcon from '../components/svgIcon/svgIcon.vue' // 组件引入
Vue.component('svg-icon', svgIcon) //挂载全局组件
//下面这个是导入svgIcon/svg下的所有svg文件
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
/*
第一个参数是:'./svg' => 需要检索的目录,
第二个参数是:false => 是否检索子目录,
第三个参数是: /\.svg$/ => 匹配文件的正则
*/
requireAll(req)
5. 在 main.js 中引入
6.使用
直接在想要用的地方用就行, 其中icon-class 后面是文件名(icons/svg/), className 后面是自己定义的类名,可以通过类名修改图标大小 和 颜色
<template>
<div>
<h3>SVG图标配置使用</h3>
<-- 驼峰或者 - 写法都可 -->
<svg-icon icon-class="pay" className="icon1"></svg-icon>
<svg-icon iconClass="TXT" class-name="icon2"></svg-icon>
</div>
</template>
<script>
export default {}
</script>
<style scoped>
/* 单色图标直接通过类名就可以修改颜色和大小 */
.icon1 {
font-size: 60px;
color: red;
}
.icon2 {
font-size: 50px;
color: blue;
}
svg path {
fill: red;
/* fill: currentColor */
}
</style>
需要注意:
- 修改时通过 font-size 修改大小,不是width, height,
- 单色图标: 直接通过自定义类名修改大小和颜色就行
- 多色图标: 直接自定义类名可以修改大小,但是颜色不会变
因为从 iconfont 下载下来的图标文件默认没有内联的 fill 属性,所以可以像上面那样直接为 svg 元素指定 fill 属性,fill 会继承给子元素;如果下载的时候选择了颜色,就会多出来内联的 fill 属性,此时需要显式指定子元素的 fill 继承自父元素(否则继承的权重很低,样式无法被应用):
修改方法(推荐方式2):
方式1:
svg path {
fill:inherit
/*
fill: red; 直接写颜色也行
*/
}
为什么这里不能写成下面这样呢?
.icon path {
fill:inherit
}
这是因为 svg->use 里面会生成一个 shadow dom,这个 shadow dom 包含了 svg->path,它是无法通过 css 选择器拿到的,所以上面这个样式声明不会起效果。
当然还可以用 currentColor 修改图标颜色。因为在元素自身没有 color 属性的时候,它的 currentColor 会继承父元素的 color 属性,所以可以给 .icon 设置 color,并指定每一个 path 的 fill 属性都是 currentColor :
.icon {
color:#fff
}
svg path {
fill:currentColor
}
这部分来自于:
https://cloud.tencent.com/developer/article/1624103
要注意的是,在vue单文件使用scoped时不生效,我使用样式穿透也没行,后面就没深专了,,多色图标这样改也会把全部颜色改成一样,还不如用单色,修改方便,所以可以用第二种方式,直接改svg文件,把对应的改成想要的颜色就行,一般ui设计师会设计好给前端用吧…
方式2:
通过直接改svg文件里面的 fill 对应的颜色修改,拉到后面就可以看到,前面都是path, 或者搜索一下,修改成想要的颜色就可,或者删除掉要修改颜色的 fill ,然后自定义类名设置的颜色就可以发挥效果了。
总结
我们可以直接下载字体图标下来引入到项目, 也可以用上面配置成组件的方式使用, 使用组件更加方便等。
其实iconfont也提供了symbol使用方式,也是推荐使用的方式,只不过现在有兼容性问题,以后这种方式会用的越来越多吧
写的不好地方多多交流…哈…呼…