Springboot3+微服务实战12306高性能售票系统-捣衣砧上拂还来
用了那么久的 SVG,你还没有入门吗
Springboot3+微服务实战12306高性能售票系统
download:https://www.51xuebc.com/thread-544-1-1.html
其真实大局部的项目中都有 直接 或 间接 运用到 SVG 和 Canvas,但是在大多数时分我们只是选择 简单理解 或 直接跳过,这有问题吗?没有问题,毕竟砖还是要搬的!
话说回来,前端其实还是需求对 SVG 和 Canvas 停止学习的,由于其实你不断都在用,多理解不会让你有什么损失,最根本的能够防止:
不至于当 UI 扔给你一个不契合设计稿颜色的 SVG 时摸不着头脑
不至于无法经过 CSS 为 SVG 图自定义其色值时无从下手
以至不晓得为什么要在项目中将展现 SVG 的内容封装成组件
...
再往上些就能够基于 SVG 停止自定义编码,例如完成各种基于 SVG 的动画需求、在可视化大屏项目中的应用等等。
相关文章其实早就想写(在草稿箱里挺长时间了),但由于各种缘由没有真正输出,本篇文章以 SVG 为主要内容正式开启探究之旅。
文中如有不正确之处,可在评论区斧正!!!
SVG 简介
人话就是说 SVG 是一种可缩放矢量图形,它能够用 类 HTML(即 XML) 来表示,也就是 可编码,因而你能够在 DOM 中直接运用,能够经过 CSS 控制款式,能够经过 JavaScript 动态修正。
具有什么优势?
其实经过上述的简介,你就不难看出 SVG 至少有以下两个优点(说多了记不住没意义):
可缩放矢量图形
可编码性
可缩放矢量图形
点阵图/位图
也就是 由很多的像素组成的图形,平常看到的大多图片数属于点阵图,但由于像素十分高,每个点十分小,人的眼睛看不清那一个个的点,所以没有感知,但其实都是用点组成的,通常将它们不断放大,就看到区别了,如下:
原始尺寸图片
经过画图软件放大
从以上来看 点阵图/位图 缺陷之一就是 不合适停止无限放大,由于会招致本来人眼不可见的像素被放大,招致视觉上看起来图片 含糊/失真。
但是也正是由于 点阵图/位图 由不同的像素块组成的,因而能够给不同的像素块填充不同颜色,使得整个图形颜色能够十分丰厚。
矢量图形
而 矢量图形 是用 数学向量、依据几何特性 来绘制图形,矢量能够是 一个点 或 一条线,它是经过 多个对象的组合生成 的,对其中的每一个对象的记载方式
并且每个对象都是一个 相互独立的实体,意味着屡次挪动和改动它的属性时不会影响图例中的其它对象,仍能够在维持它原有明晰度和弯曲度
因而,矢量图形的优点如下:
文件占用内在空间较小
矢量图实践上保管的是 点、线、矩形 等元素的信息,我们可以看到图像是由于在我们翻开矢量图时,由计算机依据这些信息计算出来的,而 点阵图/位图 则是保管各个点的图像信息
放大后不失真(不会变含糊)
由于它和分辨率无关,无论我们挪动或改动它的属性几次,它都能够在维持它原有明晰度和弯曲度
可编码性
可编码性应该不难了解,完整能够经过下面这个图来解释(一图胜千言):
SVG 的可编码性使得它相关于 点阵图/位图 具备更强的灵敏性,只需依照其对应的规则去修正 点、线 等相关信息,我们就能够改动图形,而不像 点阵图/位图 意义比方只是想要不同颜色的同一张图片用于切换时,还得单独准备两张图片等等。
SVG 的运用场景
icon
依据 name 作为标识完成援用,这里就不再展开。
平面图绘制
在项目中需求停止平面图绘制,如需求绘制 线、多边形、图片 等等,比方需求完成前端引导页功用,其中的遮罩层及高亮矩形局部就是基于 SVG 完成的
动画绘制
通常会存在需求与用户产生共鸣或互动的场景,特别是需求满足创意性排版的需求等,最常见比方公司年度回忆、一些重要内容的营销宣传等,也可基于 SVG 的方式来完成。
当然你也能够基于
SVG 根本外形元素
SVG 图像是运用各种元素创立的,这些元素分别应用于矢量图像的构造、绘制与规划,因而和 SVG 元素相关的内容是需求去理解的,但内容不算少, 按 A-Z 的次第大约包括以 A、C、D、E、F、G、H、I、L、M、P、R、S、T、U、V 等作为前缀的元素
圆形元素
是用来创立圆,它是基于一个圆心和一个半径,对应属性为:
cx 表示圆心的 X 坐标
cy 表示圆心的 Y 坐标
r 表示半径<circle cx="50" cy="50" r="50"></circle>
那么假如想要其他 html 元素一样添加 边框色 和 背风光,该怎样办呢?
SVG 元素可不是运用 border-color 和 background-color 属性完成的,而是经过 stroke 和 fill 来完成的
矩形元素
元素用来创立矩形,基于一个角位置以及它的宽和高,还能够用来创立圆角矩形,其对应属性有:
x 表示 x 轴坐标
y 表示 y 轴坐标
rx 用于定义程度轴向的圆角半径尺寸
ry 用于定义纵轴向的圆角半径尺寸
矩形 变 圆形:正方形时将 rx 或 ry 设置为宽高的一半即可,长方形时可变椭圆<rect x="25" y="25" width="100" height="100" rx="50" fill="pink" stroke="green"></rect>
椭圆元素
元素用来创立一个椭圆,基于一个 中心坐标、x 半径、y 半径:
cx 定义一个中心点的 x 轴坐标
cy 定义一个中心点的 y 轴坐标
rx 用于定义程度轴向的圆角半径尺寸
ry 用于定义纵轴向的圆角半径尺寸<ellipse cx="150" cy="75" rx="100" ry="50" fill="pink" stroke="green"></ellipse>
椭圆 变 圆形:只需求将 rx 和 ry 设置为相同值即可<ellipse cx="150" cy="75" rx="50" ry="50" fill="pink" stroke="green"></ellipse>
线条元素
用来创立一条衔接两个点的线,其属性有:
x1 表示第一个点的 x 坐标
x2 表示第二个点的 x 坐标
y1 表示第一个点的 y 坐标
y2 表示第二个点的 y 坐标
值得留意的是:需求为 stroke 赋对应的色值,否则是无法察看到效果
<line x1="50" y1="20" x2="150" y2="100" stroke="red"></line>
折线元素
是用来创立一系列直线,也就是衔接多个点,它通常创立的是一个开放的外形,即最后一点不与第一点相连,假如需求闭合方式能够运用 元素。
其专有属性为:
points 用于表示多个点的坐标:x1,y1 x2,y2 x3,y3 ... xn,yn<polyline
points="0,40 40,40 40,80 80,80 80,120 120,120 120,160"
fill="white"
stroke="red"
stroke-width="4"
></polyline>
多边形元素
元素定义了一个由一组首尾相连的直线线段构成的闭合多边形外形,最后一点衔接到第一点,其属性和 分歧,不同在于表现上。
例好像一个例子在 的表现如下:<polygon
points="0,40 40,40 40,80 80,80 80,120 120,120 120,160"
fill="white"
stroke="red"
stroke-width="4"
></polygon>
途径元素
元素是用来定义外形的通用元素,一切的根本外形都能够用 path 元从来创立。
其专有属性包括:
d 用于定义一个要绘制的途径,途径定义是一个 途径命令(下文中会引见) 组成的列表,其中的每一个命令由命令字母和用于表示命令参数的数字组成
<path
fill="#f40"
stroke="#000"
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30 z"
/>
途径命令是对要绘制的途径的阐明,每一个命令由代表命令的字母和代表参数的 数字 组成,SVG 定义了六种途径命令类型,一共 20 条命令。
挪动到:M、m
画线至:L、l、H、h、V、v
三次方贝塞尔曲线:C、c、S、s
二次方贝塞尔曲线:Q、q、T、t
椭圆曲线:A、a
封锁途径:Z、z
不难发现命令是辨别大小写的(即大小写敏感),大写 的命令指定 绝对坐标,小写 命令指定 相对坐标(相对当前位置的)。
命令中的数字能够运用 负数 方式,只不过代表的意义不同:
对 角度 而言 负数 表示是 逆时针
在 绝对坐标 中,-x 和 -y 均表示为负坐标
在 相对坐标 中,-x 值为 向左 挪动,负的 -y 值为 向上 挪动
望文生义,就是指从 当前点 挪动到 下一点,即从 当前位置(Po {xo, yo}) 挪动到 新位置(Pn {xn, yn}),并且 Pn 与 Po 之间不会绘制衔接线:
M 绝对坐标,将当前位置挪动到坐标 x,y
m 相对坐标,将当前位置沿 x 轴挪动 dx,沿 y 轴挪动 dy,即
Pn = { xo + dx, yo + dy }<path
fill="none"
stroke="#f40"
stroke-width="10"
d="M 10,10 h 30
m 0,10 h 30
m 0,10 h 30
M 40,20 h 30
m 0,10 h 30
m 0,10 h 30
m 0,10 h 30
m -30,10 h 30
m -60,10 h 30
m -60,10 h 30
m -60,10 h 30
m -60,10 h 30"
/>
Lineto 指令将绘制一条直线段,从 当前位置 (Po { xo, yo }) 移到 指定位置(Pn { xn, yn }),指定位置(Pn) 将变成下一个命令中的 当前位置(Po)**:
L 在 当前位置 和 指定位置 x,y 之间绘制 一条线段
即 Po = Pn = { x, y }
I 在 当前位置 和 指定位置 x,y 之间绘制 一条线段,指定位置 为 当前位置 沿 x 轴偏移 dx、沿 y 轴偏移 dy 处
即 Po = Pn = { xo + dx, yo + dy }
H 在 当前位置 与 指定位置 之间绘制一条 程度线段,指定位置 由 x 参数 和 当前位置的 y 坐标指定
即 Po = Pn = { x, yo }
h 在 当前位置 与 指定位置 之间绘制一条 程度线段,指定位置 由 当前位置 沿 x 轴偏移 dx 的 x 坐标 和 当前位置 的 y 坐标指定
即 Po = Pn = { xo + dx, yo }
V 在 当前位置 与 指定位置 之间绘制一条 垂直线段,指定位置 由 y 参数和 当前位置 的 x 坐标指定
即 Po = Pn = { xo, y }
v 在 当前位置 与 指定位置 之间绘制一条 垂直线段,指定位置 由 当前位置 沿 y 轴偏移 dy 的 y 坐标 和 当前位置 的 x 坐标指定
即 Po = Pn = { x, yo + dy }<path
fill="none"
stroke="#f40"
stroke-width="10"
d="M 10,10
L 100,100
V 10
H 30"
/>
三次是运用 四个点 定义的平滑曲线,绘制完成后 终点(Pn) 将成为下一个命令中的 当前位置(Po):
起始点(当前位置) — 第一个点
(Po = {xo, yo})
终点 — 第二个点
(Pn = {xn, yn})
起始控制点 — 第三个点
(*Pcs* = {xcs, ycs})(控制在起点左近的曲线的曲率)
终点控制点 — 第四个点
(Pce = {xce, yce})(控制在终点左近的曲线的曲率)
其对应的命令如下:
C
在 当前位置 和 终点 x,y 之间绘制一条三次贝塞尔曲线,起始控制点 经过 x1,y1 指定,终点控制点 经过 x2,y2 指定
参数方式为 (x1,y1, x2,y2, x,y),各点表示 **`Po = Pn = {x, y};
Pcs = {x1, y1};Pce = {x2, y2}`**
c
在 当前位置 和 终点(当前位置沿 x 轴偏移 dx、沿 y 轴偏移 dy 处)之间绘制一条三次贝塞尔曲线,起始控制点 为当前位置沿 x 轴偏移 dx1、沿 y 轴偏移 dy1 处;终点控制点 为当前位置沿 x 轴偏移 dx2、沿 y 轴偏移 dy2 处
参数方式为 (dx1,dy1, dx2,dy2, dx,dy),各点表示 Po = Pn = {xo + dx, yo + dy} ;Pcs = {xo + dx1, yo + dy1} ;Pce = {xo + dx2, yo + dy2}
S
在 当前位置 和 终点 x,y 之间绘制一条平滑的三次贝塞尔曲线,终点控制点 经过 x2,y2 指定,起始控制点 是上一条曲线命令的终点控制点在当前位置上的 反射点;若上一条命令不是曲线命令,则其与曲线的 起始点(当前位置) 相同
参数方式为 (x2,y2, x,y)
s
在 当前位置 和 终点(当前位置沿 x 轴偏移 dx、沿 y 轴偏移 dy 处)之间绘制一条平滑的三次贝塞尔曲线,终点控制点 为当前位置沿 x 轴偏移 dx2、沿 y 轴偏移 dy2 处;起始控制点 是上一条曲线命令的终点控制点在当前位置上的 反射点;若上一条命令不是曲线命令,则其与曲线的 起始点(当前位置) 相同
参数方式为 (dx2,dy2, dx,dy)<path
fill="none"
stroke="red"
d="M 10,90
C 30,90 25,10 50,10
S 70,90 90,90"
/>
<path
fill="none"
stroke="red"
d="M 110,90
c 20,0 15,-80 40,-80
s 20,80 40,80"
/>
二次是运用 三个点 定义的平滑曲线,绘制完成后 终点(Pn) 将成为下一个命令中的 当前位置(Po) :
起始点(当前位置)
Po = {xo, yo} — 第一个点
终点
Pn = {xn, yn} — 第二个点
控制点 — 第三个点
Pc = {xc, yc}(控制曲率)
其对应命令如下:
Q
在 当前位置 和 终点 x,y 之间绘制一条二次贝塞尔曲线,控制点 经过 x1,y1 指定
参数方式为 (x1,y1, x,y),各点表示 Po = Pn = {x, y} ;Pc = {x1, y1}
q
在 当前位置 和 终点(当前位置沿 x 轴偏移 dx、沿 y 轴偏移 dy 处)之间绘制一条二次贝塞尔曲线,控制点 为 当前位置(曲线的起始点)沿 x 轴偏移 dx1、沿 y 轴偏移 dy1 处
参数方式为 (dx1,dy1, dx,dy),各点表示 Po = Pn = {xo + dx, yo + dy} ;Pc = {xo + dx1, yo + dy1}
T
在 当前位置 和 终点 x,y 之间绘制一条平滑的二次贝塞尔曲线,控制点 是上一条曲线命令的控制点在当前位置上的 反射点;若上一条命令不是曲线命令,则其与曲线的 起始点(当前位置) 相同
参数方式为 (x, y),各点表示 Po = Pn = {x, y}
t
在 当前位置 和 终点(当前位置沿 x 轴偏移 dx、沿 y 轴偏移 dy 处)之间绘制一条平滑的二次贝塞尔曲线,控制点 是上一条曲线命令的控制点在当前位置上的 反射点;若上一条命令不是曲线命令,则其与曲线的 起始点(当前位置) 相同
参数方式为 (dx, dy),各点表示 Po = Pn = {xo + dx, yo + dy}<path
fill="none"
stroke="red"
d="M 10,50
Q 25,25 40,50
t 30,0 30,0 30,0 30,0 30,0"
/>
椭圆曲线 实践上就是用来定义为椭圆的一局部的曲线,当需求绘制 高度规则的曲线 时运用 椭圆曲线 相比于 贝塞尔曲线 会更容易:
A
在 当前位置 和 坐标 x,y 之间绘制一条椭圆曲线,用于绘制圆弧的椭圆中心依据命令的其他参数肯定,参数方式 (rx ry angle large-arc-flag sweep-flag x y)
坐标 x,y 将成为下一个命令中的当前位置
a
在 当前位置 和 指定位置 之间绘制一条椭圆曲线,指定位置 为当前位置沿 x 轴偏移 dx、沿 y 轴偏移 dy 处,用于绘制圆弧的椭圆中心依据命令的其他参数肯定,参数方式 (rx ry angle large-arc-flag sweep-flag dx dy)
坐标 dx,dy 将成为下一个命令中的当前位置
A 和 a 共同参数表示如下:
rx 和 ry 是椭圆的两个半径
angle 表示椭圆相关于 x 轴的旋转角度
large-arc-flag 和 sweep-flag 允许选择必需绘制的弧线,由于其他参数能够绘制 4 条可能的弧线
large-arc-flag 允许选择 一个 大弧线(1)或 一个 小弧线(0)
sweep-flag 允许选择一条 顺时针 旋转的 弧线(1)或一条 逆时针 旋转的 弧线(0)
<svg stroke-width="4">
<path
fill="none"
stroke="red"
d="M 150,50
A 150 50 10 1 0 14,10"
/>
<path
fill="none"
stroke="lime"
d="M 150,50
A 150 50 10 1 1 14,10"
/>
<path
fill="none"
stroke="purple"
d="M 150,50
A 150 50 10 0 1 14,10"
/>
<path
fill="none"
stroke="pink"
d="M 150,50
A 150 50 10 0 0 14,10"
/>
ClosePath 命令将从 当前位置 绘制一条 直线 到 途径中的 第一个点,其对应的命令为 Z 或 z,没有什么参数,并且大小写不敏感。<path
fill="pink"
stroke="red"
d="M 150,50
l -10,50 80,0
z"
/>
根底案例理论
由于文章篇幅有限,第一个案例会说得细一些,后续的案例就不再逐个细致剖析了。
环形进度条
这个应该是比拟常见的一个需求了,但是假如不让运用组件库你打算怎样完成?
要是没有理解 SVG 之前,恐怕连这么个看似简单的效果都不好完成,但是如今我们能够借助 SVG 来完成,或者我们先来看看组件库是怎样完成的:
以上是 ElementUi 中的完成,没错就是 SVG ,如今你晓得其实你项目里不断都有在用 SVG 了吧!
简单剖析
整体能够看成是 两个圆形 堆叠,因而能够经过 元素完成(也能够选择 元素,如上述给出的例图)
元素默许是会绘制整个圆,但是进度条肯定不是一开端就是 100% 的,因而能够运用 stroke-dashoffset 属性 来将完好的圆变成局部的,但是直接运用 stroke-dashoffset 属性是不会生效的,由于它要配合 stroke-dasharray 属性 一同来运用
指定 dash 形式 到 途径开端 的间隔控制用来描边的 点划线 的图案范式,其实你完整能够分离 border: 1px solid dash 来了解,就是用于将一段连续的内容变成非连续的,设置了它就开启了 dash 形式
静态完成<circle cx="150" cy="75" r="50" stroke="#ebeef5" fill="none"></circle>
<circle
class="process-circle"
cx="150"
cy="75"
r="50"
stroke="#20a0ff"
transform="rotate(-90 150 75)"
fill="none"
stroke-dasharray="314"
stroke-dashoffset="314"
></circle>
添加动画
经过以上的方式就完成了一个静态的环形进度条了,接下来就需求它动起来,由于 stroke-dasharray(在这它的值其实就是圆的周长) 和 stroke-dashoffset 的属性值是需求动态生成的,因而我们得添加一些 JavaScript 代码:
function setProcessCircle(percent = 0) {
const processCircle = document.querySelector('.process-circle')
// 获取圆的周长
const circumference = processCircle.getTotalLength()
// 把周长赋值给 strokeDasharray
processCircle.style.strokeDasharray = circumference
// 动态计算 offset 赋值给 strokeDashoffset
// 为了支持 percent = 0 | '0%',所以运用 parseInt 转换
processCircle.style.strokeDashoffset =
circumference * (1 - parseInt(percent) / 100)
}
效果图中的 html + css 局部就不贴出来了,容易占篇幅。
loading 动画
例如 ElementUI 中 区域加载 的 loading 方式如下:
简单剖析
察看整体不难发现只需求一个圆形,即便用 元素即可
其蓝色局部不断在 缩短 或 增长,这点能够经过 stroke-dasharray 和 stroke-dashoffset 属性来完成,同时添加 transition 过渡动画即可
最后是每个 缩短 或 增长 的位置不是相同的,那么能够直接用过动画 animation 和 roate 来完成停的旋转即可
按钮动效
简单剖析
外层包裹的矩形能够经过 元素完成
矩形的线条残缺不完好,能够经过 stroke-dasharray 和 stroke-dashoffset 属性来完成
当鼠标放置上去时,产生的动画可经过 animation、stroke-dasharray 、stroke-dashoffset 等属性分离即可
复杂案例实战
以上的根底案例由于触及的计算不多,因而我们能够人工停止计算宽、高、偏移等等数据,但是针对复杂的内容,很多参数就不是那么容易计算出来了,因而,我们需求一些工具来快速得到一些必要参数,然后我们在基于这些必要参数取做修正,让其产生更丰厚的效果即可。
还是同样的第一个案例这里尽量讲细致点,后续案例就不再述说过于细致的内容了。
运用 figma 创立文字途径如下
由于文字内容的途径很难直接计算处置,因而我们能够经过 figma 来协助我们生成相应的文字途径,大致操作如下:
处置 SVG 代码内容
得到的 SVG 内容大致如下,代码内容比拟多这里用图片替代,其中各个内容的对应关系如下
其中的 需求去掉,否则文字的颜色值将无法填充。
stroke-dasharray & stroke-dashoffset 属性
由于我们需求让文字具备断续衔接的才能,这里还是得运用前面提到 stroke-dasharray 和 stroke-dashoffset 属性来完成,它们的功用前面曾经描绘过了,也用了几次了,假如你不记得了能够回过头去看看。
但是这里的 stroke-dasharray 和 stroke-dashoffset 的值到底该设置成几呢?
首先一定是设置成每个文字的长度,那么问题就变成了怎样获取文字的长度了,不用担忧
animation 动画
反复的事交给 JavaScript
简单剖析
完成以上效果需求包括以下几个内容:
获取 目的物 的 SVG 代码
绘制 运动途径
让目的物 沿着途径运动
获取目的物的 SVG 代码
绘制运动途径
运动途径的绘制我们依然能够经过 SVG 工具 figma 来获取,值得留意的是默许的途径是用还是填充的,真正在应用时能够经过 stroke="transparent" 将途径颜色变成透明色,整体感官更好,大致如下:
让目的物沿着途径运动
中心就是引入