1. SVG简介
-
SVG,即可缩放矢量图形( Scalable Vector Graphics),是一种 XML应用
- 来描述二维图形和绘图程序的语言
-
SVG指可伸缩矢量图形
-
SVG用来定义用于网络的基于矢量的图形
-
SVG使用XML格式定义图形
-
SVG图像在放大或改变尺寸的情况下其图形质量不会有所损失,即不会失真
-
SVG 可以制作成整体或局部动画
-
SVG 图像可以与DOM,CSS和JavaScript交互
-
SVG 可以被记事本等阅读器、搜索引擎访问
-
SVG 图像中的文本是可选的,同时也是可复制的
-
相比其它位图,SVG图像文件更小,可压缩性更强
-
SVG 提供了一些图像编辑效果,比如屏蔽和剪裁、应用过滤器等等
-
SVG 只是文本,因此可以使用 GZip 对其进行有效压缩。
2. SVG和Canvas区别
- canvas是html5的新特征,而svg存在的历史已经很久了
- svg所描绘的图形为矢量图,所以用法上收到了限制,只能描绘矢量图
- 而svg中不能引入普通的图片
- 由于本质为矢量图,而百度地图就是用svg技术来做出来的
- canvas所描绘的图形为位图,,你会看到canvas里面的图形和文字会失真
- canvas支持颜色比svg多
3. 插入SVG的N种方式总结
1、使用svg标签
- 直接把SVG整个标签内容丢到HTML中即可
2、使用img标签
<img src="./test.svg" style="display:block;width:330px;height:240px" />
3、使用iframe标签
- 万能的iframe当然什么都能显示,但是无法控制内容大小 -- viewBox也搞不定,估计只能用百分比来定位了,太麻烦了,一般不使用
<iframe src="./test.svg" style="display:block;width:330px;height:240px;border:none;" ></iframe>
4、使用embed标签
- 注意使用viewBox,标签的兼容性也很不错的,是个不错的选择。
<embed src="./test.svg" style="display:block;width:330px;height:240px" />
5、使用object标签
<object>与<embed>类似,也要注意配置viewBox.
<object type="image/svg+xml" data="./test.svg" style="display:block;width:330px;height:240px" >
<param name="src" value="./test.svg" >
</object>
6、使用div的背景图片
- svg图片是可以作为背景图片的。不过和
<img>标签一样,无法显示SVG内嵌的.
<div style="display:block;width:330px;height:240px;background: url(./test.svg) no-repeat;background-size: 100%;" ></div>
//css
.loading-three-dots{
background-image: url('data:image/svg+xml,<svg width="120" height="30" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="%23b5edf5"><circle cx="15" cy="15" r="15"><animate attributeName="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="60" cy="15" r="9" fill-opacity="0.3"><animate attributeName="r" from="9" to="9" begin="0s" dur="0.8s" values="9;15;9" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="0.5" to="0.5" begin="0s" dur="0.8s" values=".5;1;.5" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="105" cy="15" r="15"><animate attributeName="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcMode="linear" repeatCount="indefinite" /></circle></svg>');
}
html
<div class="loading loading-three-dots"></div>
background-image内联svg注意事项
- svg内容需要被url-转义才能执行,例如。#被替换为%23
- 可使用SVG转义工具
7、使用picture标签
<picture>标签是HTML5新增的一个专门显示图片的标签。
注意设置<source>标签的属性srcset而非src. 此外必需要添加一个<img>标签,不过可以在<img>标签中指定另外一张图片,以便在浏览器无法显示<source>指定的图片的时候显示<img>标签中的图片。
<picture>和<img>一样,无法显示SVG内嵌的<image>.
<picture >
<source srcset="./test.svg" type="image/svg+xml">
<img src="./test.png" style="display:block;width:330px;height:240px">
</picture>
4. SVG的基本图形和属性
图形
<rect>:矩形<circle>:圆形<ellipse>:椭圆<line>:直线<polyline>:折现<polygon>:多边形<path>:路径
属性
fill:填充stroke:描边颜色transform:图形变换opacity:不透明度
stroke属性
1、stroke-width
- 描边的粗细
2、stroke-linecap
- 控制边框终点的形状
- 属性的值有三种可能值
butt用直边结束线段,它是常规做法,线段边界90度垂直于描边的方向、贯穿它的终点square和butt效果差不多,但是会稍微超出实际路径的范围,超出的大小由stroke-width控制。-
round表示边框的终点是圆角,圆角的半径也是由stroke-width控制的
- 属性的值有三种可能值
3、stroke-dasharray
- 用于创建虚线,之所以后面跟的是array的,是因为可以是多个参数
stroke-dasharray = '10'
stroke-dasharray = '10, 5'
stroke-dasharray = '20, 10, 5'
上面代码理解:
stroke-dasharray为一个参数时:其实是表示虚线长度和每段虚线之间的间距 如:stroke-dasharray = '10' 表示:虚线长10,间距10,然后重复 虚线长10,间距10
两个参数或者多个参数时:一个表示长度,一个表示间距 如:stroke-dasharray = '10, 5' 表示:虚线长10,间距5,然后重复 虚线长10,间距5 如:stroke-dasharray = '20, 10, 5' 表示:虚线长20,间距10,虚线长5,接着是间距20,虚线10,间距5,之后开始如此循环
4、stroke-dashoffset
- 属性指定了dash模式到路径开始的距离
5、stroke-linejoin
- 控制两条描边线段之间,用什么方式连接
- 属性的值有三种可能值
miter是默认值,表示用方形画笔在连接处形成尖round表示用圆角连接,实现平滑效果bevel,连接处会形成一个斜接
- 属性的值有三种可能值
6、stroke-opacity
- 描边透明度
4.1 矩形 <rect>
属性如下
- x :属性定义矩形的左侧位置
- y :属性定义矩形的顶端位置
- width :矩形的宽
- height :矩形的高
- rx :rx定义圆角的宽
- ry :ry定义圆角的高
- 矩形的圆角效果,是用rx,ry定义的
4.2 圆形 <circle>
属性如下
- cx :定义圆点的X坐标
- cy :定义圆点的y坐标
- r :定义圆的半径
4.3 椭圆 <ellipse>
1 、椭圆与圆很相似。不同之处在于椭圆有不同的x和y半径,而圆的x和y半径是相同的
2 、椭圆其实就是在圆的基础上增加了维度的半径
属性如下
- cx :定义的椭圆中心的x坐标
- cy :定义的椭圆中心的y坐标
- rx :定义的水平半径
- ry :定义的垂直半径
4.4 直线 <line>
直线:描述2个点定义一条直线
属性如下
- x1
- y1
- x2
- y2
4.5 折线 <polyline>
折现:是一组连接在一起的直线。因为它可以有很多的点,折线的的所有点位置都放在一个
points属性中
属性
- points
- 格式 :points="x1 y2,x2 y2....."
- 点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。
- 如:
<polyline points="60 110, 65 120, 70 115, 75 130, 80 125, 85 140, 90 135, 95 150, 100 145"/>
4.6 多边形 <polygon>
polygon和折线很像,它们都是由连接一组点集的直线构成。不同的是,polygon的路径在最后一个点处自动回到第一个点。需要注意的是,矩形也是一种多边形,如果需要更多灵活性的话,你也可以用多边形创建一个矩形
属性
- points
- 格式 :points="x1 y2,x2 y2....."
- 点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。所以点列表 (0,0), (1,1) 和(2,2)可以写成这样:“0 0, 1 1, 2 2”。
4.7 路径 <path>
-参考:developer.mozilla.org/zh-CN/docs/…
path可能是SVG中最常见的形状。你可以用path元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状,例如贝塞尔曲线、2次曲线等曲线。因为path很强大也很复杂
属性
- d :一个点集数列以及其它关于如何绘制路径的信息
- 属性d的值是一个“命令+参数”的序列
- 每一个命令都用一个关键字母来表示,比如,字母“M”表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点
- 跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标。比如移动到(10,10)这个点的命令,应该写成“M 10 10”
- 这一段字符结束后,解析器就会去读下一段命令。每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位
- 属性d采用的是用户坐标系统,所以不需标明单位
4.7.1 svg的 <path>命令
M = moveto
M x y 移动到指定坐标,xy分别为x轴和y轴的坐标点,类似画笔的起点。
L = lineto
L x y 在初始位置(M 画的起点)和xy确定的坐标画一条线。 两点一线,直线,绘图中很常见的方式。
H = horizontal lineto
H x 沿着x轴移动一段位置
V = vertical lineto
V y 沿着y轴移动一段位置
C = curveto
C x1 y1 x2 y2 x y 三次贝塞尔曲线
S = smooth curveto
S x2 y2 x y 简化的贝塞尔曲线
1.如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。
2.如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点。
Q = quadratic Bézier curve
Q x1 y1 x y 二次贝塞尔曲线Q 只需要一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。
T = smooth quadratic Bézier curveto
Q命令的简写命令。
与S命令相似,T也会通过前一个控制点,推断出一个新的控制点。1.T命令前面必须是一个Q命令,或者是另一个T命令
2.如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线
A = elliptical Arc
A rx,ry x-axis-rotation large-arc-flag sweep-flag x,y rx 弧的半长轴长度 ry 弧的半短轴长度 x-axis-rotation 是此段弧所在的x轴与水平方向的夹角,即x轴的逆时针旋转角度,负数代表顺时针旋转角度。 large-arc-flag 为1表示大角度弧线,0表示小角度弧线 sweep-flag 为1表示从起点到终点弧线绕中心顺时针方向,0表示逆时针方向。 xy 是终点坐标。
Z = closepath
从当前位置到起点画一条直线闭合。
注意:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
4.7.2 直线命令
<path>元素里有5个画直线的命令,顾名思义,直线命令就是在两个点之间画直线。首先是“Move to”命令,M,前面已经提到过,它需要两个参数,分别是需要移动到的点的x轴和y轴的坐标。假设,你的画笔当前位于一个点,在使用M命令移动画笔后,只会移动画笔,但不会在两点之间画线。因为M命令仅仅是移动画笔,但不画线。所以M命令经常出现在路径的开始处,用来指明从何处开始画。
- 格式
M x y
or
m dx dy
4.7.3 曲线命令
绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,另外一个用来绘制弧形或者说是圆的一部分。如果你在Inkscape、Illustrator或者Photoshop中用过路径工具,可能对贝塞尔曲线有一定程度的了解。欲了解贝塞尔曲线的完整数学讲解,请阅读这份Wikipedia的文档。在这里不用讲得太多。贝塞尔曲线的类型有很多,但是在path元素里,只存在两种贝塞尔曲线:三次贝塞尔曲线C,和二次贝塞尔曲线Q。
5. SVG基本操作API
5.1 创建图形
//创建一个具有指定的命名空间URI和限定名称的元素
//要创建一个元素而不指定命名空间URI,请使用createElement 方法。
let element =
document.createElementNS(namespaceURI, name[, options]);
参数
- namespaceURI
指定与元素相关联的命名空间URI的字符串。创建的元素的namespaceURI属性使用namespaceURI的值进行初始化
- name
字符串值,可为此元素节点规定其名称。
- options (可选的)
一个可选的包含单个属性的ElementCreationOptions对象,其值是预先使用customElements.define()定义的自定义元素的标签名称。为了向后兼容自定义元素规范的早期版本,一些浏览器允许您在此使用字符串替代对象,其中字符串的值是自定义元素的标签名称。
返回值
- 新元素
5.1.1 有效的命名空间URI
HTML - 参阅 www.w3.org/1999/xhtml
SVG - 参阅 www.w3.org/2000/svg
XBL - 参阅 www.mozilla.org/xbl
XUL - 参阅 www.mozilla.org/keymaster/g…
5.2 添加图形
element.appendChild(childElement)
5.3 设置/获取属性
element.setAttribute(name,value)
element.getAttribute(name)
6. 简单的SVG编辑器
7.在线SVG压缩和转义工具
- 支持选择SVG文件上传,支持拖拽上传,也支持直接粘贴SVG代码进行压缩
- 例如从iconfont.cn网站随便下一个SVG图标,然后上传下,还有将近40%的压缩比:
- www.zhangxinxu.com/sp/svgo/
8. SVG Sprites还原与管理的在线工具
- 每个SVG小图标可以独立下载,也可以复制内联SVG代码,或者base64代码或者作为CSS背景使用的转义SVG代码。内置1500多个 Font Awesome小图标,对于一些要求不高的项目,可以直接复制这些小图标。
- www.zhangxinxu.com/sp/icon/
9.验证 SVG
-
SVG 文件是 XML,可以用无效的格式编写,有些服务或应用程序可能不接受无效的 SVG 文件。
-
SVG 可以使用validator.w3.org/验证
10. SVG的世界: 视野、视窗的概念
视窗:是浏览器渲染出来的一个区域
视野:是SVG文件编写者定义的多大的视野观察世界
11. SVG颜色表示
SVG和canvas中是一样的,都是使用标准的HTML/CSS中的颜色表示方法,这些颜色都可以用于fill和stroke属性。
基本有下面这些定义颜色的方式:
1、颜色名字: 直接使用颜色名字red, blue, black…
2.rgba/rgb值: 这个也很好理解,例如#ff0000,rgba(255,100,100,0.5)。
3.十六进制值: 用十六进制定义的颜色,例如#ffffff。
4.渐变值:这个也与canvas中一样,支持两种渐变色:线性渐变,径向渐变。
5、图案填充:使用自定义的图案作为填充色。
12. 渐变
12.1 线性渐变
线性渐变沿着直线改变颜色,要插入一个线性渐变,你需要在SVG文件的defs元素内部,创建一个
<linearGradient>节点即可定义线性渐变。每一个渐变色成分使用stop元素定义。
12.2 径向渐变
径向渐变是从一个点开始发散绘制渐变,创建径向渐变需要在文档的defs中添加一个
<radialGradient>元素
12.3 <stop>节点元素
一个渐变上的颜色坡度,是用stop元素定义的。stop元素可以是
<linearGradient>元素或者<radialGradient>元素的子元素这些结点通过指定位置的offset(偏移)属性和stop-color(颜色中值)属性来说明在渐变的特定位置上应该是什么颜色;可以直接指定这两个属性值,也可以通过CSS来指定他们的值
13. 结构元素
<defs>,<g>,<svg>,<symbol>,<use>
13.1 <defs> 元素
1、SVG 允许我们定义以后需要重复使用的图形元素。 建议把所有需要再次使用的引用元素定义在defs元素里面。
2、这样做可以增加SVG内容的易读性和可访问性。
3、在defs元素中定义的图形元素不会直接呈现。 你可以在你的视口的任意地方利用<use>元素呈现这些元素。
13.2 <use> 元素
1、use元素在SVG文档内取得目标节点,并在别的地方复制它们。
2、use元素还可以跨SVG调用
3、出于安全原因,一些浏览器可能在use元素上应用同源策略,还有可能拒绝载入xlink:href属性内的跨源URI。
4、use元素是通过xlink:href属性,寻找要使用的元素的
use 复制调用例子
- 如果我们用了好多给坐标值绘制了半天,如果想弄一个同样的类型,只是位置不同,这时候如果复制一遍代码,会造成我们的代码冗余,因此我们就可以使用
use特性重复调用节点
<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>
代码理解:
use元素是通过xlink:href属性,寻找要使用的元素的。#shape对应的就是id为shape的元素。use元素可以有自己的坐标,以及支持transform变换,甚至可以use其他use元素。
这里,两个use元素使用的是同一个g元素(组合),从而实现了图形的重复调用功能。
use 跨SVG调用例子
- SVG中的use元素可以调用其他SVG文件的元素,只要在一个文档中。
紧接着上面的SVG复制调用的例子
<svg width="500" height="110"><use xlink:href="#shape" x="50" y="50" /></svg>
其实跨SVG调用就是“SVG Sprite技术”的核心所在
13.3 <g>元素
1、g是group(分组)的缩写。
2、<g>元素通常用来对相关图形元素进行分组,盔甲统一操作,例如旋转,缩放或添加相关样式等
3、<g>元素的属性会被其所有的子元素继承
4、<g>元素也可以用来定义复杂的对象,之后可以通过<use>元素来引用它们
5、<g>分组定义的内容直接会显示
13.4 <symbol>元素
1、symbol元素用来定义一个图形模板对象,它可以用一个<use>元素实例化
2、<symbol>能够创建自己的视窗,因此能够应用viewBox和preserveAspectRatio属性
3、一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的 <use>元素)才能呈现。
14. SVG动画
14.1 animate元素
- svg中
animate元素可以用于实现动画效果,属性如下- attributeName 定义发生变化的元素属性名
- attributeType 当attributeType="XML"时,attributeName被认为是XML的属性;当attributeType="CSS"时,attributeName被认为是css的属性;不指定attributeType时,默认为"auto",会先将attributeName作为css的属性,如果无效,再将attributeName作为XML的属性。
- from、to、by from和to分别定义发生变化的属性的初始值和终止值。from可缺省,表示初始值即为animate父元素相应的属性值。可用by替换to,表示变化偏移量。
- begin、dur、end begin定义动画开始时间;dur定义动画所需时间(持续时间);end定义动画终止时间。时间单位h:小时;min:分钟;s:秒;ms:毫秒。默认时间单位为:s
- fill 当fill="freeze"时,动画终止时,发生变化的元素属性值停留在动画终止时的状态;当fill="remove"时,动画终止时,发生变化的元素属性值回复到动画起始时的状态。fill属性默认值为:remove
<rect x="10" y="10" width="200" height="20" stroke="green" fill="none">
<animate attributeName="width" attributeType="XML"
from="20" to="200" begin="0s" dur="3s" fill="freeze" />
</rect>
- 以上代码会实现一个绿色正方形逐渐拉长的动画。
14.2 animateTransform 元素
- 实现transform属性改变的动画,使用animateTransform来替代animate元素
- animateTransform的attributeName被指定为transform
- 用type属性指定需要改变的属性,如:translate,scale,rotate,skewX,skewY等。和css3的transform属性值一样
- animateTransform还有个additive属性。默认情况下additive属性值为replace,表示当前animateTransform的初始状态与之前的animateTransform变化结果无关,如果additive="sum",表示当前animateTransform的变化基于之前的animateTransform变化之上、
<rect x="10" y="10" width="20" height="20" style="fill: #ff9; stroke: black;">
<animateTransform id="a1" attributeName="transform" attributeType="XML" type="scale" from="1" to="4 2" additive="sum" begin="0s" dur="4s" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="45" additive="sum" begin="a1.end" dur="4s" fill="freeze"></animateTransform>
</rect>
14.3 animateMotion 元素
-
animateMotion可以实现单凭css动画属性无法实现的效果。
-
animateMotion可以让父元素沿着指定的路径运动,如:
-
animateMotion有个rotate属性,默认为0,元素在运动时不会旋转。当设置为auto时,元素对应的水平轴会始终与path路径保持水平
<g>
<rect x="0" y="0" width="50" height="30" style="fill: #ccc;"/>
<circle cx="40" cy="30" r="10" style="fill: #fff; stroke: black;"/>
<circle cx="10" cy="30" r="10" style="fill: #fff; stroke: black;"/>
<animateMotion path="M50,125 C 100,25 150,225, 200, 125" dur="4s" fill="freeze"/>
</g>
14.4 小例子
Loading效果
- 利用background-image属性显示svg动画作为loading状态,注意url后需要添加数据说明:data:image/svg+xml, 来表示这是sv
公共css
.loading {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-size: cover;
}
HTML
<div class="loading loading-audio"></div>
<div class="loading loading-ball-triangle"></div>
<div class="loading loading-bars"></div>
<div class="loading loading-circles"></div>
<div class="loading loading-grid"></div>
<div class="loading loading-oval"></div>
<div class="loading loading-puff"></div>
<div class="loading loading-spinning-circles"></div>
<div class="loading loading-tail-spin"></div>
<div class="loading loading-three-dots"></div>
CSS
.loading-audio {
background-image: url('data:image/svg+xml,<svg width="55" height="80" viewBox="0 0 55 80" xmlns="http://www.w3.org/2000/svg" fill="#9fe8e0"><g transform="matrix(1 0 0 -1 0 80)"><rect width="10" height="20" rx="3"><animate attributeName="height" begin="0s" dur="4.3s" values="20;45;57;80;64;32;66;45;64;23;66;13;64;56;34;34;2;23;76;79;20" calcMode="linear" repeatCount="indefinite" /></rect><rect x="15" width="10" height="80" rx="3"><animate attributeName="height" begin="0s" dur="2s" values="80;55;33;5;75;23;73;33;12;14;60;80" calcMode="linear" repeatCount="indefinite" /></rect><rect x="30" width="10" height="50" rx="3"><animate attributeName="height" begin="0s" dur="1.4s" values="50;34;78;23;56;23;34;76;80;54;21;50" calcMode="linear" repeatCount="indefinite" /></rect><rect x="45" width="10" height="30" rx="3"><animate attributeName="height" begin="0s" dur="2s" values="30;45;13;80;56;72;45;76;34;23;67;30" calcMode="linear" repeatCount="indefinite" /></rect></g></svg>')
}
.loading-ball-triangle {
background-image: url('data:image/svg+xml,<svg width="57" height="57" viewBox="0 0 57 57" xmlns="http://www.w3.org/2000/svg" stroke="#9fbde8"><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)" stroke-width="2"><circle cx="5" cy="50" r="5"><animate attributeName="cy" begin="0s" dur="2.2s" values="50;5;50;50" calcMode="linear" repeatCount="indefinite" /><animate attributeName="cx" begin="0s" dur="2.2s" values="5;27;49;5" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="27" cy="5" r="5"><animate attributeName="cy" begin="0s" dur="2.2s" from="5" to="5" values="5;50;50;5" calcMode="linear" repeatCount="indefinite" /><animate attributeName="cx" begin="0s" dur="2.2s" from="27" to="27" values="27;49;5;27" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="49" cy="50" r="5"><animate attributeName="cy" begin="0s" dur="2.2s" values="50;50;5;50" calcMode="linear" repeatCount="indefinite" /><animate attributeName="cx" from="49" to="49" begin="0s" dur="2.2s" values="49;5;27;49" calcMode="linear" repeatCount="indefinite" /></circle></g></g></svg>');
}
.loading-bars {
background-image: url('data:image/svg+xml,<svg width="135" height="140" viewBox="0 0 135 140" xmlns="http://www.w3.org/2000/svg" fill="#c19fe8"><rect y="10" width="15" height="120" rx="6"><animate attributeName="height" begin="0.5s" dur="1s" values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" repeatCount="indefinite" /><animate attributeName="y" begin="0.5s" dur="1s" values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" repeatCount="indefinite" /></rect><rect x="30" y="10" width="15" height="120" rx="6"><animate attributeName="height" begin="0.25s" dur="1s" values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" repeatCount="indefinite" /><animate attributeName="y" begin="0.25s" dur="1s" values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" repeatCount="indefinite" /></rect><rect x="60" width="15" height="140" rx="6"><animate attributeName="height" begin="0s" dur="1s" values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" repeatCount="indefinite" /><animate attributeName="y" begin="0s" dur="1s" values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" repeatCount="indefinite" /></rect><rect x="90" y="10" width="15" height="120" rx="6"><animate attributeName="height" begin="0.25s" dur="1s" values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" repeatCount="indefinite" /><animate attributeName="y" begin="0.25s" dur="1s" values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" repeatCount="indefinite" /></rect><rect x="120" y="10" width="15" height="120" rx="6"><animate attributeName="height" begin="0.5s" dur="1s" values="120;110;100;90;80;70;60;50;40;140;120" calcMode="linear" repeatCount="indefinite" /><animate attributeName="y" begin="0.5s" dur="1s" values="10;15;20;25;30;35;40;45;50;0;10" calcMode="linear" repeatCount="indefinite" /></rect></svg>');
}
.loading-circles {
background-image: url('data:image/svg+xml,<svg width="135" height="135" viewBox="0 0 135 135" xmlns="http://www.w3.org/2000/svg" fill="#e8b69a"><path d="M67.447 58c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10zm9.448 9.447c0 5.523 4.477 10 10 10 5.522 0 10-4.477 10-10s-4.478-10-10-10c-5.523 0-10 4.477-10 10zm-9.448 9.448c-5.523 0-10 4.477-10 10 0 5.522 4.477 10 10 10s10-4.478 10-10c0-5.523-4.477-10-10-10zM58 67.447c0-5.523-4.477-10-10-10s-10 4.477-10 10 4.477 10 10 10 10-4.477 10-10z"><animateTransform attributeName="transform" type="rotate" from="0 67 67" to="-360 67 67" dur="2.5s" repeatCount="indefinite"/></path><path d="M28.19 40.31c6.627 0 12-5.374 12-12 0-6.628-5.373-12-12-12-6.628 0-12 5.372-12 12 0 6.626 5.372 12 12 12zm30.72-19.825c4.686 4.687 12.284 4.687 16.97 0 4.686-4.686 4.686-12.284 0-16.97-4.686-4.687-12.284-4.687-16.97 0-4.687 4.686-4.687 12.284 0 16.97zm35.74 7.705c0 6.627 5.37 12 12 12 6.626 0 12-5.373 12-12 0-6.628-5.374-12-12-12-6.63 0-12 5.372-12 12zm19.822 30.72c-4.686 4.686-4.686 12.284 0 16.97 4.687 4.686 12.285 4.686 16.97 0 4.687-4.686 4.687-12.284 0-16.97-4.685-4.687-12.283-4.687-16.97 0zm-7.704 35.74c-6.627 0-12 5.37-12 12 0 6.626 5.373 12 12 12s12-5.374 12-12c0-6.63-5.373-12-12-12zm-30.72 19.822c-4.686-4.686-12.284-4.686-16.97 0-4.686 4.687-4.686 12.285 0 16.97 4.686 4.687 12.284 4.687 16.97 0 4.687-4.685 4.687-12.283 0-16.97zm-35.74-7.704c0-6.627-5.372-12-12-12-6.626 0-12 5.373-12 12s5.374 12 12 12c6.628 0 12-5.373 12-12zm-19.823-30.72c4.687-4.686 4.687-12.284 0-16.97-4.686-4.686-12.284-4.686-16.97 0-4.687 4.686-4.687 12.284 0 16.97 4.686 4.687 12.284 4.687 16.97 0z"><animateTransform attributeName="transform" type="rotate" from="0 67 67" to="360 67 67" dur="8s" repeatCount="indefinite"/></path></svg>');
}
.loading-grid {
background-image: url('data:image/svg+xml,<svg width="105" height="105" viewBox="0 0 105 105" xmlns="http://www.w3.org/2000/svg" fill="#d4f39f"><circle cx="12.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="0s" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="12.5" cy="52.5" r="12.5" fill-opacity=".5"><animate attributeName="fill-opacity" begin="100ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="52.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="300ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="52.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="600ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="92.5" cy="12.5" r="12.5"><animate attributeName="fill-opacity" begin="800ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="92.5" cy="52.5" r="12.5"><animate attributeName="fill-opacity" begin="400ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="12.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="700ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="52.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="500ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="92.5" cy="92.5" r="12.5"><animate attributeName="fill-opacity" begin="200ms" dur="1s" values="1;.2;1" calcMode="linear" repeatCount="indefinite" /></circle></svg>');
}
.loading-oval {
background-image: url('data:image/svg+xml,<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#efe1a4"><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)" stroke-width="2"><circle stroke-opacity=".5" cx="18" cy="18" r="18"/><path d="M36 18c0-9.94-8.06-18-18-18"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="1s" repeatCount="indefinite"/></path></g></g></svg>');
}
.loading-puff {
background-image: url('data:image/svg+xml,<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#a0d9f1"><g fill="none" fill-rule="evenodd" stroke-width="2"><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /><animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /></circle><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /><animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /></circle></g></svg>');
}
.loading-spinning-circles {
background-image: url('data:image/svg+xml,<svg width="58" height="58" viewBox="0 0 58 58" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g transform="translate(2 1)" stroke="#FFF" stroke-width="1.5"><circle cx="42.601" cy="11.462" r="5" fill-opacity="1" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="1;0;0;0;0;0;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="49.063" cy="27.063" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;1;0;0;0;0;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="42.601" cy="42.663" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;1;0;0;0;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="27" cy="49.125" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;0;1;0;0;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="11.399" cy="42.663" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;0;0;1;0;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="4.938" cy="27.063" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;0;0;0;1;0;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="11.399" cy="11.462" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;0;0;0;0;1;0" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="27" cy="5" r="5" fill-opacity="0" fill="#efa2dd"><animate attributeName="fill-opacity" begin="0s" dur="1.3s" values="0;0;0;0;0;0;0;1" calcMode="linear" repeatCount="indefinite" /></circle></g></g></svg>');
}
.loading-tail-spin {
background-image: url('data:image/svg+xml,<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a"><stop stop-color="#f5fda9" stop-opacity="0" offset="0%"/><stop stop-color="#f5fda9" stop-opacity=".631" offset="63.146%"/><stop stop-color="#f5fda9" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)"><path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke="url(#a)" stroke-width="2"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" /></path><circle fill="#fff" cx="36" cy="18" r="1"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" /></circle></g></g></svg>');
}
.loading-three-dots{
background-image: url('data:image/svg+xml,<svg width="120" height="30" viewBox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="#b5edf5"><circle cx="15" cy="15" r="15"><animate attributeName="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="60" cy="15" r="9" fill-opacity="0.3"><animate attributeName="r" from="9" to="9" begin="0s" dur="0.8s" values="9;15;9" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="0.5" to="0.5" begin="0s" dur="0.8s" values=".5;1;.5" calcMode="linear" repeatCount="indefinite" /></circle><circle cx="105" cy="15" r="15"><animate attributeName="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcMode="linear" repeatCount="indefinite" /><animate attributeName="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcMode="linear" repeatCount="indefinite" /></circle></svg>');
}
解决Loading效果打开浏览器,一片空白
- 上面的css代码,
background-image的url()内联SVG留了点坑,浏览器打开会发现一片空白 - 请注意: svg内容需要被url-转义才能执行,例如。
#被替换为%23,即可显示效果
效果
在vue中封装使用svg
1、首先我们创建一个专门放置图标 icon 的文件夹如:
@/src/icons,将所有 icon 放在这个文件夹下。 之后我们就要使用到 webpack 的 require.context。很多人对于require.context可能比较陌生,直白的解释就是
- require.context("./test", false, /.test.js$/); 这行代码就会去 test 文件夹(不包含子目录)下面的找所有文件名以
.test.js结尾的文件能被 require 的文件。 更直白的说就是 我们可以通过正则匹配引入相应的文件模块。require.context有三个参数:
- directory:说明需要检索的目录
- useSubdirectories:是否检索子目录
- regExp: 匹配文件的正则表达式
2、在src目录下创建icons文件及子文件svg和index.js并配置从svg文件夹中读取svg文件
1. 下载插件 svg-sprite-loader
github:github.com/JetBrains/s…
svg-sprite-loader是Webpack加载器,用于创建SVG精灵,可以实现自己的icon组件
它的工作原理是: 利用svg的symbol元素,将每个icon包括在symbol中,通过use元素使用该symbol.
npm i svg-sprite-loader --save
2.vue.config.js (webpack配置)
/*
* @Descripttion: vue.config.js的配置
* @version:
*/
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
module.exports = {
chainWebpack(config) {
// config.plugins.delete('preload') // TODO: need test
// config.plugins.delete('prefetch') // TODO: need test
// set svg-sprite-loader
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()
},
}
3.在components公共组件文件夹下创建SvgIcon文件夹下的index.vue并加入以下组件配置代码
index.vue
<!--
* @Descripttion: svg组件
* @version:
* @Author: sueRimn
* @Date: 2019-12-14 15:01:04
* @LastEditors: sueRimn
* @LastEditTime: 2019-12-14 19:04:11
-->
<template>
<svg :class="svgClass"
aria-hidden="true"
v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
iconName () {
return `#icon-${this.iconClass}`
},
svgClass () {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
4、svg文件夹
-
src/icon/Svg
-
将复制好的svg图标代码放到src下icon文件夹的子文件svg下
<svg t="1576321314655" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5136" width="200" height="200"><path d="M391.25 820.42c21.862 0 39.584-17.726 39.584-39.584 0-21.862-17.722-39.582-39.584-39.582-21.858 0-39.582 17.72-39.582 39.582C351.668 802.694 369.392 820.42 391.25 820.42zM628.754 820.42c21.858 0 39.584-17.726 39.584-39.584 0-21.862-17.724-39.582-39.584-39.582-21.866 0-39.584 17.72-39.584 39.582C589.168 802.694 606.888 820.42 628.754 820.42zM510 10C233.858 10 10 233.858 10 510s223.858 500 500 500 500-223.858 500-500S786.142 10 510 10zM824.774 333.832l-57.484 249.086-19.792 0-435.414 35.418 0 4.166c0 21.86 17.722 39.582 39.584 39.582l455.208 0c0 19.956 0.62 39.582 0 39.582l-178.122 0c43.72 0 79.166 35.444 79.166 79.168 0 43.724-35.444 79.17-79.166 79.17-43.724 0-79.168-35.444-79.168-79.17 0-43.724 35.444-79.168 79.168-79.168L391.25 701.666c43.724 0 79.168 35.444 79.168 79.168 0 43.724-35.444 79.17-79.168 79.17-43.72 0-79.166-35.444-79.166-79.17 0-43.724 35.444-79.168 79.166-79.168l-39.582 0c-43.724 0-79.168-35.442-79.168-79.164L272.5 266.254l-59.374 0c-10.932 0-19.792-8.862-19.792-19.792 0-10.93 8.86-19.798 19.792-19.798l118.75 0c10.928 0 19.792 8.868 19.792 19.798 0 10.93-8.864 19.792-19.792 19.792l-19.792 0 0 39.582 494.792 0c10.93 0 19.792 8.86 19.792 19.792C826.668 328.578 825.932 331.318 824.774 333.832zM312.084 581.358l424.392-33.508 50.606-202.428-475 0L312.082 581.358z" p-id="5137" data-spm-anchor-id="a313x.7781069.0.i8" class="selected" fill="#d4237a"></path></svg>
5、index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon' // svg组件
// register globally 注册为全局组件
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
6、main.js
- 在main.js中全局引入icon
import '@/icons' // icon
7、在组件中使用
- iconClass是你保存在
icon下svg文件下的svg名称.
<svg-icon iconClass="car"/>
参考
-
嵌入SVG图片的N种方式: segmentfault.com/a/119000001…
-
SVG精简压缩工具、SVG Sprites还原与管理的在线工具:www.zhangxinxu.com/wordpress/2…