Vorwort
Im täglichen Entwicklungsprozess wurden wir mehr oder weniger ausgesetzt SVG
, es kann verwendet werden, um einige einfache Grafiken zu zeichnen, es kann verwendet werden, um die Schriftartdateibibliothek des Projekts zu erstellen, oder es wird sogar verwendet, um einige komplexe Visualisierungsmodule zu zeichnen. Dieser Artikel beschreibt SVG
die grundlegenden Grafiken und gängigen Formen der Animation, um Ihnen den Einstieg zu erleichtern SVG
.
grundlegende Grafiken
Im Folgenden werden SVG
einige voreingestellte Formen und entsprechende Attribute vorgestellt.Im eigentlichen Entwicklungs- oder Designprozess werden die SVG
meiste Zeit einige Werkzeuge zum Zeichnen von Symbolen verwendet.
Rechteck
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="100" x="20" y="20" rx="30" ry="30" style="fill:rgb(255,255,0);stroke-width:4;
stroke:rgb(0,0,0);fill-opacity: .6;stroke-opacity: .5;" />
</svg>
复制代码
Im svg
Label width
bedeutet es die gesamte Breite, die height
Höhe, die version
Version und den xmlns
Namensraum.Die letzten beiden Attribute sind relativ feste Dinge, die ein wenig nachvollzogen werden können.
rect
Die Tag-Attribute und style
Attribute in werden wie folgt erklärt:
width
:Breiteheight
:hochx
: Versatz in horizontaler Richtungy
: Versatz in vertikaler Richtungrx
,ry
: Definieren Sie den abgerundeten Eckeneffektstyle
: Stile (diese Stile gelten auch für die Grafiken unten, daher werden die Grafiken unten nur Eigenschaften einführen und Stile nicht wiederholen)fill
: RGB-Farbe, die die Füllfarbe des Rechtecks angibtfill-opacity
: Deckkraft der Füllungstroke
: RGB-Farbe, die die Rahmenfarbe des Rechtecks angibtstroke-width
: Die Größe des rechteckigen Rahmensstroke-opacity
: Deckkraft des Rechteckrandes
runden
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="50" r="40" style="stroke:black; stroke-width:2; fill:blue" />
</svg>
复制代码
circle
Die Tag-Attribute werden wie folgt erklärt:
cx
,cy
: Koordinaten des Kreismittelpunktesr
: der Radius des Kreises
Oval
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="100" cy="50" rx="40" ry="50" style="fill:purple" />
</svg>
复制代码
ellipse
Die Tag-Attribute werden wie folgt erklärt:
cx
: diex
Koordinaten des Kreismittelpunktscy
: diey
Koordinaten des Kreismittelpunktsrx
: horizontaler Radiusry
: vertikaler Radius
Linie
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<line x1="10" y1="10" x2="100" y2="100" style="stroke:red;stroke-width:2" />
</svg>
复制代码
line
Die Tag-Attribute werden wie folgt erklärt:
x1
:x
Koordinaten des Startpunkts des Liniensegmentsx2
: Koordinaten des Endpunkts desx
Liniensegmentsy1
:y
Koordinaten des Startpunkts des Liniensegmentsy2
: Koordinaten des Endpunkts desy
Liniensegments
Polygon
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<polygon points="10,10 10,200 100,200 100,10" style="fill:red;
stroke:#000000;stroke-width:1" />
</svg>
复制代码
polygon
Die Tag-Attribute werden wie folgt erklärt:
points
: Definieren Sie die Koordinaten des PolygonsN
(x
, ), nicht weniger als drei Punktey
Polylinie
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<polyline points="10,10 20,20 30,15 40,40 50,30 60,60" style="fill:transparent;stroke:green;stroke-width:2" />
</svg>
复制代码
polyline
Die Tag-Attribute werden wie folgt erklärt:
points
: Definiere die Koordinaten der KurveN
(x
, )y
PS:你看这个曲线图,像不像你最近的股票基金
路径
path
标签中用属性d
来描述路径,花样非常多,我们一个一个来看。
M
moveto
,看意思是移动到某个点,想象你手里拿着一根笔,M命令就是让你的笔尖移动到某个点,准备开始绘画。语法为M(x,y)
,其中大写M
表示绝对定位,小写m
表示相对定位,下面的其他语法也一样。
Z
closepath
,闭合你前面所画的路径。
L
lineto
,意思为画一条线,语法为L(x,y)
。
<svg width="100%" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 L200 200 Z" style="stroke: red;stroke-width:2" />
</svg>
复制代码
H
horizontal lineto
,水平地画一条线。语法为H(y)
<svg width="100%" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 H200 Z" style="stroke: red;stroke-width:2" />
</svg>
复制代码
V
vertical lineto
,竖直地画一条线。语法为V(x)
<svg width="100%" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 V200 Z" style="stroke: red;stroke-width:2" />
</svg>
复制代码
C
curveto
,三次贝塞尔曲线。语法为C x1 y1, x2 y2, x y
。三次贝塞尔曲线应该有四个点来控制,C
中只描述了三个点,所以起始点是你用M
描述的。举个例子:M10 10 C 100 100 150 100 200 10
,指的是起始点为(10,10)
,第一个辅助点为(100,100)
,第二个辅助点为(150,100)
,终止点为(200,10)
控制的三次贝塞尔曲线。
S
smooth curveto
,用来描述对称的三次贝塞尔曲线。语法为S x2 y2, x y
。当S跟在S命令或者C命令之后时,它的第一个控制点(即S语法中省略掉的x1 y1)会被假设为前一个控制点的对称点,如果前面没有跟S或者C命令,它的两个控制点会被视为同一个点。
<svg width="100%" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 S 100 100 200 10" style="stroke: red;stroke-width:1;fill:white" />
</svg>
<svg width="100%" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M100 100 C 150 150 200 150 250 100 S 300 20 400 100" style="stroke: red;stroke-width:1;fill:white" />
</svg>
复制代码
复制代码
Q
二次贝塞尔曲线,只需要一个控制点。语法为Q x1 y1, x y
<svg width="100%" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 Q100 100 200 0" style="stroke: red;stroke-width:1;fill:white" />
</svg>
复制代码
T
与S
类似,通过前一个控制点,推断出新的控制点。语法为T x y
<svg width="100%" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="red" fill="transparent" />
</svg>
复制代码
A
elliptical Arc
,椭圆弧。语法为A rx ry x-axis-rotation large-arc-flag sweep-flag x y
rx
、ry
椭圆弧的两个半轴长度,如果相等就是圆弧x-axis-rotation
椭圆相对于坐标系的旋转角度large-arc-flag
绘制优弧(1),劣弧(0)sweep-flag
顺时针绘制(1),逆时针绘制(0)x
y
圆弧终点坐标
<svg width="100%" height="100vh" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M200 200 H300 V100 A 100 100 0 1 1 200 200" style="stroke: red;stroke-width:2;fill:white" />
</svg>
复制代码
路径的绘制十分复杂。。建议使用SVG
编辑器来辅助绘画图形。
SVG
动画
在上面我们了解了各种SVG
的图形及语法,SVG
除了可以画出各种各样的图形之外,它的动画效果也是别树一帜的。我们下面来了解一下SVG
常见的动画形式以及应用。
描边动画
下面先介绍两个属性,stroke-dasharray
和stroke-dashoffset
。我们实现的描边动画是围绕这两个属性展开的。
stroke-dasharray
用于创造虚线,语法为stroke-dasharray:n1 [n2 [n3]]
。什么意思呢?先来看下面几个例子
<svg width="100vw" height="100vh" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M0 100 H400" class="line" style="stroke-dasharray: 10;"></path>
<path d="M0 200 H400" class="line" style="stroke-dasharray: 10 20;"></path>
<path d="M0 300 H400" class="line" style="stroke-dasharray: 10 20 30;"></path>
</svg>
复制代码
配合上图,我们可以总结一下stroke-dasharray
的规则:
- 一个参数时描述实线虚线的长度相等,比如
stroke-dasharray: 10
就表示描述这条路径的时候,10长度
的实线->10长度
的虚线->10长度
的实线···如此循环。 - 两个参数时描述实线长度是第一个参数,虚线长度是第二个参数,
stroke-dasharray: 10 20
表示10长度
实线->20长度
虚线->10长度
实线···如此循环。 - 三个参数时描述实线虚线长度交替进行,
stroke-dasharray: 10 20 30
表示10长度
实线->20长度
虚线->30长度
实线->10长度
虚线···如此循环。
stroke-dashoffset
表示虚线的偏移量,值为正数时表示向反方向偏移,值为负数表示向正方向偏移。
<svg width="100vw" height="100vh" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M0 100 H400" class="line" style="stroke-dasharray: 400;stroke-dashoffset:200"></path>
</svg>
复制代码
由图可以看出,我们把路径分成了400实线400虚线的展示形式,通过将虚线从反方向偏移200,就可以把实线的200长度遮起来,就完成了图中只剩半截的路径。自此,我们已经可以利用这两个属性来做一个路径动画了,无非就是将这两个属性配合CSS
的animation
动画而已。
先从简单的开始,比如像下面的直线从无到有动画:
.line {
stroke-width: 4px;
stroke: red;
stroke-dasharray: 400;
stroke-dashoffset: 400;
animation: move 2s;
}
@keyframes move {
to {
stroke-dashoffset: 0;
}
}
<svg width="100vw" height="100vh" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M0 100 H400" class="line"></path>
</svg>
复制代码
在有了上诉简单的从无到有动画之后,其实不难发现它不仅仅只能作用于一条简单的直线上,例如我们现在有一个SVG图形如下,同样也可以做一个描边动画。
在开始之前,先介绍path
元素中的一个方法——getTotalLength()
,该方法返回路径总长度(以用户单位为单位)的计算值。我们可以利用它计算任意path
元素的总长度。
有了上述的知识之后,我们大概做了一个上面的动画,这里是实现的代码
<style>
.path {
stroke-width: 4px;
stroke: white;
stroke-dasharray: 5199.931640625;
stroke-dashoffset: 5199.931640625;
animation: move 2s linear;
fill: white;
animation-fill-mode: forwards;
}
@keyframes move {
to {
stroke-dashoffset: 0;
stroke: black;
transform: scale3d(1.1, 1.1, 1.1);
}
}
.scale {
stroke-dashoffset: 0;
stroke: black;
animation: scale-path .2s;
animation-fill-mode: forwards;
opacity: 0;
}
@keyframes scale-path {
0% {
transform: scale3d(1, 1, 1);
fill: white;
opacity: 0;
}
50% {
transform: scale3d(1.2, 1.2, 1);
}
100% {
transform: scale3d(1, 1, 1);
opacity: 1;
fill: black;
}
}
</style>
<svg class="icon" viewBox="0 0 2000 2000" version="1.1" xmlns="http://www.w3.org/2000/svg"
width="200" height="200">
<path class="path" d="......"p-id="2506"></path>
</svg>
<script>
const path = document.querySelector('.path')
setTimeout(() => {
$(path).addClass('scale')
}, 2000)
</script>
复制代码
路径跟随动画
路径跟随动画是另一种SVG
常见的动画形式,即让一个物体沿着SVG
图形的路径移动。开始之前先来了解一个path
元素的方法:getPointAtLength(number):Point
,它的入参是一个数字,值为0~getTotalLength()
,返回值为该长度对应下的点的坐标。了解了这个之后,我们只要把路径长度分为N
份,可以获得N
个点的坐标,让受控的元素的坐标逐步的赋值为这N
个点的坐标,就可以做到元素跟随SVG
路径移动的效果,具体实现逻辑如下:
const STEP = 1000
let currentStep = 1
const path = document.querySelector('.path');
const length = path.getTotalLength();
const slider = document.querySelector('.slider')
setInterval(() => {
const point = path.getPointAtLength(currentStep / STEP * length)
slider.style.top = point.y - 10 + 'px' //10是滑块宽度的一半,为了更好的贴合路径
slider.style.left = point.x - 10 + 'px'
if (currentStep === STEP) {
currentStep = 1
} else {
currentStep++
}
}, 10)
复制代码
在获取到具体坐标之后,我们只需要用一个定时器把坐标不断赋值,就可以实现路径跟随效果。但是在上述效果中,注意到滑块的角度是没有变化的,导致在圆弧部分视觉上并不能体现出跟随的效果,也就是说我们还需要求出滑块对应的旋转角度。
这里注意到我们是把路径点分成了N
个,因为点足够的多,坐标变化足够的快,所以我们看起来是连续的,实际上移动的时候还是离散的。计算机的抽样都是这样,只要抽样点足够的多,就会无限逼近平滑的曲线。
所以要求滑块在某一个点的角度,可以先求出滑块在此处的切线斜率。在这个情景下,假设当前点的坐标是(x2,y2)
,上一个点的坐标是(x1,y1)
,那么k=(y2-y1)/(x2-x1)
这条线段的斜率,只要这条线段足够的短,就可以当作是滑块目前的斜率,求出斜率之后使用反正切三角函数Math.atan
可以求出倾斜角,注意,这里得出来的角度单位是弧度,我们还需要把它转成角度才能用在rotate
中。
let prePos
setInterval(() => {
//......
if (prePos) {
const k = (point.y - prePos.y) / (point.x - prePos.x)
const val = Math.atan(k) / Math.PI * 180
slider.style.transform = `rotate(${val}deg)`
}
prePos = point
//......
}, 10)
复制代码
加上角度偏移后,可以感觉得到路径的贴合度更高,视觉效果更好。