Erste Schritte mit SVG-Beispielen und Animationskämpfen

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 SVGdie grundlegenden Grafiken und gängigen Formen der Animation, um Ihnen den Einstieg zu erleichtern SVG.

grundlegende Grafiken

Im Folgenden werden SVGeinige voreingestellte Formen und entsprechende Attribute vorgestellt.Im eigentlichen Entwicklungs- oder Designprozess werden die SVGmeiste 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 svgLabel widthbedeutet es die gesamte Breite, die heightHöhe, die versionVersion und den xmlnsNamensraum.Die letzten beiden Attribute sind relativ feste Dinge, die ein wenig nachvollzogen werden können.

rectDie Tag-Attribute und styleAttribute in werden wie folgt erklärt:

  • width:Breite
  • height:hoch
  • x: Versatz in horizontaler Richtung
  • y: Versatz in vertikaler Richtung
  • rx, ry: Definieren Sie den abgerundeten Eckeneffekt
  • style: 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 ​​angibt
    • fill-opacity: Deckkraft der Füllung
    • stroke: RGB-Farbe, die die Rahmenfarbe des Rechtecks ​​angibt
    • stroke-width: Die Größe des rechteckigen Rahmens
    • stroke-opacity: Deckkraft des Rechteckrandes

3qz0hdjxmp.png

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>
复制代码

circleDie Tag-Attribute werden wie folgt erklärt:

  • cx, cy: Koordinaten des Kreismittelpunktes
  • r: der Radius des Kreises

kodyreue0m.png

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>
复制代码

ellipseDie Tag-Attribute werden wie folgt erklärt:

  • cx: die xKoordinaten des Kreismittelpunkts
  • cy: die yKoordinaten des Kreismittelpunkts
  • rx: horizontaler Radius
  • ry: vertikaler Radius

a7zb5k027t.png

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>
复制代码

lineDie Tag-Attribute werden wie folgt erklärt:

  • x1: xKoordinaten des Startpunkts des Liniensegments
  • x2: Koordinaten des Endpunkts des xLiniensegments
  • y1: yKoordinaten des Startpunkts des Liniensegments
  • y2: Koordinaten des Endpunkts des yLiniensegments

kykch4aear.png

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>
复制代码

polygonDie Tag-Attribute werden wie folgt erklärt:

  • points: Definieren Sie die Koordinaten des Polygons N( x, ), nicht weniger als drei Punktey

6wvc4w2o5p.png

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>
复制代码

polylineDie Tag-Attribute werden wie folgt erklärt:

  • points: Definiere die Koordinaten der Kurve N( x, )y

pdm5limgx9.png

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>
复制代码

qr1hhvkbrs.png

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>
复制代码

tj78adful1.png

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>
复制代码

u2ng8yl2ac.png

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)控制的三次贝塞尔曲线。

hswuywj4cq.png

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>
复制代码

6vdi1kdw9o.png

复制代码

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>
复制代码

9atyjzekeu.png

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>
复制代码

2ps7ht25qv.png

A

elliptical Arc,椭圆弧。语法为A rx ry x-axis-rotation large-arc-flag sweep-flag x y

  • rxry椭圆弧的两个半轴长度,如果相等就是圆弧
  • 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>
复制代码

scewwfkro0.png

路径的绘制十分复杂。。建议使用SVG编辑器来辅助绘画图形。

SVG动画

在上面我们了解了各种SVG的图形及语法,SVG除了可以画出各种各样的图形之外,它的动画效果也是别树一帜的。我们下面来了解一下SVG常见的动画形式以及应用。

描边动画

下面先介绍两个属性,stroke-dasharraystroke-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>
复制代码

h6hp66re6t.png

配合上图,我们可以总结一下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>
复制代码

vwgag7dgww.png

由图可以看出,我们把路径分成了400实线400虚线的展示形式,通过将虚线从反方向偏移200,就可以把实线的200长度遮起来,就完成了图中只剩半截的路径。自此,我们已经可以利用这两个属性来做一个路径动画了,无非就是将这两个属性配合CSSanimation动画而已。

先从简单的开始,比如像下面的直线从无到有动画:

af1vr6ms4m.gif

.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图形如下,同样也可以做一个描边动画。

driliu9cfy.png

在开始之前,先介绍path元素中的一个方法——getTotalLength(),该方法返回路径总长度(以用户单位为单位)的计算值。我们可以利用它计算任意path元素的总长度。

xaz7trmg0c.gif

有了上述的知识之后,我们大概做了一个上面的动画,这里是实现的代码

<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>
复制代码

路径跟随动画

x951k9jbyg.gif

路径跟随动画是另一种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)

复制代码

vd0vslnpt4.gif

加上角度偏移后,可以感觉得到路径的贴合度更高,视觉效果更好。

Supongo que te gusta

Origin juejin.im/post/7077948833631731748
Recomendado
Clasificación