SVG实例入门与动画实战

小温侯
• 阅读 921

前言

在日常开发过程中,我们或多或少都接触过SVG,有可能是用它来画一些简单的图形,有可能是使用它来构建工程的字体文件库,甚至是用它来绘制一些复杂的可视化模块。本文会详细介绍SVG的基本图形以及常见的动画形式,帮助你了解入门SVG

基本图形

下面会介绍SVG预设的数种形状以及对应的属性介绍,在实际开发或者设计过程中,绘画SVG图标大多数时候都是会使用一些工具的。

矩形

    <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>

svg标签中,width表示整个宽度,height表示高度,version表示版本,xmlns表示命名空间,后面两个属性是相对固定的东西,稍作理解即可。

rect中的标签属性与style属性解释如下:

  • width:宽度
  • height:高度
  • x:水平方向上的偏移量
  • y:竖直方向上的偏移量
  • rxry:定义圆角效果
  • style:样式(这些样式同样适用于下面的图形,所以下面的图形只会介绍属性,不会重复介绍样式)

    • fill:rgb颜色,表示矩形的填充颜色
    • fill-opacity:填充的不透明度
    • stroke:rgb颜色,表示矩形的边框颜色
    • stroke-width:矩形边框的大小
    • stroke-opacity:矩形边框的不透明度

SVG实例入门与动画实战

圆形

<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标签属性解释如下:

  • cxcy:圆心坐标
  • r:圆的半径

SVG实例入门与动画实战

椭圆

<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标签属性解释如下:

  • cx:圆心的x坐标
  • cy:圆心的y坐标
  • rx:水平半径
  • ry:竖直半径

SVG实例入门与动画实战

线条

<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标签属性解释如下:

  • x1:线段的起点x坐标
  • x2:线段的终点x坐标
  • y1:线段的起点y坐标
  • y2:线段的终点y坐标

SVG实例入门与动画实战

多边形

<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标签属性解释如下:

  • points:定义多边形的N个(x,y)坐标,不少于三个点

SVG实例入门与动画实战

折线

<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标签属性解释如下:

  • points:定义曲线的N个(x,y)坐标

SVG实例入门与动画实战

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>

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>

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>

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

SVG实例入门与动画实战

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>

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>

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>

SVG实例入门与动画实战

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>

SVG实例入门与动画实战

路径的绘制十分复杂。。建议使用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>

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>

SVG实例入门与动画实战

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

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

SVG实例入门与动画实战

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

SVG实例入门与动画实战

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

SVG实例入门与动画实战

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

<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常见的动画形式,即让一个物体沿着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)

SVG实例入门与动画实战

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
App复杂动画实现——Rive保姆级教程
在App开发过程中,如果想实现动画效果,可以粗略分为两种方式。一种是直接用代码编写,像平移、旋转等简单的动画效果,都可以这么干,如果稍微复杂点,就会对开发工程师的数学功底、图形图像学功底有很高的要求。
徐小夕 徐小夕
4年前
如何使用css3实现一个类在线直播的队列动画
之前在群里有个朋友问了这样一个问题,就是如何在小程序中实现类似直播平台的用户上线时的队列动画?作为一名前端工程师,解决方案无非以下2种:1.使用javascript根据条件来控制元素的样式实现队列动画2.用纯css3配合数据驱动模型来实现.大家都知道在现代的Web开发中,我们能使用Css实现的效果尽量不要用Js,所以我们应该优先考虑用C
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
Python内置海龟(turtle)库绘图命令详解(一)
    本文主要介绍了用Python内置turtle库绘制图形的一些主要命令,turtle库是Python语言中一个很流行的绘制图像的函数库,原理是利用一个小海龟,坐标系原点(0,0)位置开始,根据一组函数指令的控制,在平面坐标系中移动,利用它爬行过的路径即可绘制图形。下面介绍turtle绘图的一些基础知识。!(https://oscimg
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
如何利用策略模式避免冗长的 if
策略模式。在实际的项目开发中,这个模式也比较常用。最常见的应用场景是,利用它来避免冗长的ifelse或switch分支判断。不过,它的作用还不止如此。它也可以像模板模式那样,提供框架的扩展点等等。对于策略模式。本篇我们讲解策略模式的原理和实现,以及如何用它来避免分支判断逻辑。后续我会通过一个具体的例子,来详细讲解策略模式的应用场景以及真正的设计意图
美凌格栋栋酱 美凌格栋栋酱
4个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
小温侯
小温侯
Lv1
写不成书,只记得、相思一点。
文章
3
粉丝
0
获赞
0