关于前端:用了那么久的-SVG你还没有入门吗

5次阅读

共计 14846 个字符,预计需要花费 38 分钟才能阅读完成。

前言

欢送关注同名公众号《熊的猫》,后续文章会同步更新!

其实在大部分的我的项目中都有 间接 间接 应用到 SVGCanvas,然而在大多数时候咱们只是抉择 简略理解 或 间接跳过,这有问题吗?没有问题, 毕竟砖还是要搬的

话说回来,前端其实还是须要对 SVGCanvas 进行学习的,因为其实你始终都在用,多理解不会让你有什么损失,最根本的能够防止:

  • 不至于当 UI 扔给你一个不合乎设计稿色彩的 SVG 时摸不着头脑
  • 不至于无奈通过 CSS 为 SVG 图自定义其色值时无从下手
  • 甚至不晓得为什么要在我的项目中将展现 SVG 的内容封装成组件

再往上些就能够基于 SVG 进行自定义编码,例如实现各种基于 SVG 的动画需要、在可视化大屏我的项目中的利用等等。

相干文章其实早就想写(在草稿箱里挺长时间了),但因为各种起因没有真正输入,本篇文章以 SVG 为次要内容正式开启探索之旅。

文中如有不正确之处,可在评论区斧正!!!

SVG 简介

是什么?

SVG 的全称是 Scalable Vector Graphics(即 可缩放矢量图形),它基于 XML 标记语言,用于形容二维的 矢量图形

同时 SVG 是一个基于文本的凋谢网络规范,其 图像内容 相干行为 会被定义于 XML 文本文件之中,并可能和 CSS、DOM、JavaScript 等网络规范进行连接。

以上是 官网解释 ,那么再给一个 非官方解释

人话就是说 SVG 是一种可缩放矢量图形,它能够用 类 HTML(即 XML) 来示意,也就是 可编码,因而你能够在 DOM 中间接应用,能够通过 CSS 管制款式,能够通过 JavaScript 动静批改。

具备什么劣势?

其实通过上述的简介,你就不难看出 SVG 至多有以下两个长处(说多了记不住没意义):

  • 可缩放矢量图形
  • 可编码性

可缩放矢量图形

点阵图 / 位图

通常咱们经见的 如 JPEG(后缀名为 .jpg.jpeg)和 PNG 属于 点阵图 / 位图

也就是 由很多的像素组成的图形,平时看到的大多图片数属于点阵图,但因为像素十分高,每个点十分小,人的眼睛看不清那一个个的点,所以没有感知,但其实都是用点组成的,通常将它们始终放大,就看到区别了,如下:

  • 原始尺寸图片

  • 通过画图软件放大

从以上来看 点阵图 / 位图 毛病之一就是 不适宜进行有限放大,因为会导致本来人眼不可见的像素被放大,导致视觉上看起来图片 含糊 / 失真

然而也正是因为 点阵图 / 位图 由不同的像素块组成的,因而能够给不同的像素块填充不同色彩,使得整个图形色调能够十分丰盛。

矢量图形

矢量图形 是用 数学向量、依据几何个性 来绘制图形,矢量能够是 一个点 或 一条线,它是通过 多个对象的组合生成 的,对其中的每一个对象的记录形式,都是以数学 函数 来实现的。

并且每个对象都是一个 相互独立的实体 ,意味着屡次挪动和扭转它的属性时不会影响图例中的其它对象,仍能够在维持它原有清晰度和蜿蜒度,也就是说它们能够按 最高分辨率 显示到 输出设备 上。

因而,矢量图形的长处如下:

  • 文件占用外在空间较小

    • 矢量图实际上保留的是 点、线、矩形 等元素的信息,咱们可能看到图像是因为在咱们关上矢量图时,由计算机依据这些信息计算出来的,而 点阵图 / 位图 则是保留各个点的图像信息
  • 放大后不失真(不会变含糊)

    • 因为它和分辨率无关,无论咱们挪动或扭转它的属性多少次,它都能够在维持它原有清晰度和蜿蜒度

可编码性

可编码性应该不难理解,齐全能够通过上面这个图来解释(一图胜千言):

SVG 的可编码性使得它绝对于 点阵图 / 位图 具备更强的灵活性,只有依照其对应的规定去批改 点、线 等相干信息,咱们就能够扭转图形,而不像 点阵图 / 位图 意义比方只是想要不同色彩的同一张图片用于切换时,还得独自筹备两张图片等等。

SVG 的应用场景

icon 图标

在我的项目中某些图标也会应用 SVG 的格局,最常见的例如在 iconfont 上可自行抉择是否以 SVG 的形式应用:

而在我的项目中应用 SVG 文件时,通常须要对应的 loader 解决,例如 vite 中的 vite-svg-loaderwebpakc 中的 svg-sprite-loader 等,还会封装成组件的模式去应用,实际上就是通过 <svg>、<symbol>、<use> 依据 name 作为标识实现援用,这里就不再开展。

平面图绘制

在我的项目中须要进行平面图绘制,如须要绘制 线、多边形、图片 等等,比方须要实现前端疏导页性能,其中的遮罩层及高亮矩形局部就是基于 SVG 实现的,详情可见往期文章 不应用第三方库怎么实现【前端疏导页】性能?

动画绘制

通常会存在须要与用户产生共鸣或互动的场景,特地是须要满足创意性排版的需要等,最常见比方公司年度回顾、一些重要内容的营销宣传等,也可基于 SVG 的形式来实现。

当然你也能够基于 greensock(一个业界出名的工具套件)实现疾速应用基于 SVG 的动画模式,如下:

SVG 根本形态元素

SVG 图像是应用各种元素创立的,这些元素别离利用于矢量图像的构造、绘制与布局,因而和 SVG 元素相干的内容是须要去理解的,但内容不算少,按 A-Z 的程序大略包含以 A、C、D、E、F、G、H、I、L、M、P、R、S、T、U、V 等作为前缀的元素,按类别还能够分类为:

  • 根本形态元素
  • 容器元素
  • 描述性元素
  • 滤镜元素
  • 字体元素

在本文中咱们将焦点关注在 根本形态元素 上。

<circle> 圆形元素

<circle> 是用来创立圆,它是基于一个圆心和一个半径,对应属性为:

  • cx 示意圆心的 X 坐标
  • cy 示意圆心的 Y 坐标
  • r 示意半径
<svg>
    <circle cx="50" cy="50" r="50"></circle>
</svg>

从上图能够看得出来 <svg> 默认的宽高为 300 * 150

那么如果想要其余 html 元素一样增加 边框色 背景色,该怎么办呢?

SVG 元素可不是应用 border-colorbackground-color 属性实现的,而是通过 strokefill 来实现的:

 <svg>
    <circle cx="50" cy="50" r="50" fill="pink" stroke="green"></circle>
 </svg>

<rect> 矩形元素

<rect> 元素用来创立矩形,基于一个角地位以及它的宽和高,还能够用来创立圆角矩形,其对应属性有:

  • x 示意 x 轴坐标
  • y 示意 y 轴坐标
  • rx 用于定义程度轴向的圆角半径尺寸
  • ry 用于定义纵轴向的圆角半径尺寸

惯例矩形:

<svg>
   <rect x="25" y="25" width="100" height="100" fill="pink" stroke="green"></rect>
</svg>

圆角矩形:

<svg>
   <rect x="25" y="25"  width="100" height="100" rx="10" fill="pink" stroke="green"></rect>
</svg>

矩形 变 圆形:正方形时将 rx 或 ry 设置为宽高的一半即可,长方形时可变椭圆

<svg>
   <rect x="25" y="25"  width="100" height="100" rx="50" fill="pink" stroke="green"></rect>
</svg>

<ellipse> 椭圆元素

<ellipse> 元素用来创立一个椭圆,基于一个 核心坐标、x 半径、y 半径:

  • cx 定义一个中心点的 x 轴坐标
  • cy 定义一个中心点的 y 轴坐标
  • rx 用于定义程度轴向的圆角半径尺寸
  • ry 用于定义纵轴向的圆角半径尺寸
<svg>
   <ellipse cx="150" cy="75" rx="100" ry="50" fill="pink" stroke="green"></ellipse>
 </svg>

椭圆 变 圆形:只须要将 rx 和 ry 设置为雷同值即可

<svg>
   <ellipse cx="150" cy="75" rx="50" ry="50" fill="pink" stroke="green"></ellipse>
</svg>

<line> 线条元素

<line> 用来创立一条连贯两个点的线,其属性有:

  • x1 示意第一个点的 x 坐标
  • x2 示意第二个点的 x 坐标
  • y1 示意第一个点的 y 坐标
  • y2 示意第二个点的 y 坐标

值得注意的是:须要为 stroke 赋对应的色值,否则是无奈察看到成果

  <svg>
    <line x1="50" y1="20" x2="150" y2="100" stroke="red"></line>
  </svg>

<polyline> 折线元素

<polyline> 是用来创立一系列直线,也就是连贯多个点,它通常创立的是一个凋谢的形态,即最初一点不与第一点相连,如果须要闭合模式能够应用 <polygon> 元素。

其专有属性为:

  • points 用于示意多个点的坐标:x1,y1 x2,y2 x3,y3 … xn,yn
<svg>
    <polyline
    points="0,40 40,40 40,80 80,80 80,120 120,120 120,160"
    fill="white" 
    stroke="red" 
    stroke-width="4"
    ></polyline>
</svg>

<polygon> 多边形元素

<polygon> 元素定义了一个由一组首尾相连的直线线段形成的闭合多边形形态,最初一点连贯到第一点,其属性和 <polygon> 统一,不同在于体现上。

例如同一个例子在 <polygon> 的体现如下:

<svg>
    <polygon
      points="0,40 40,40 40,80 80,80 80,120 120,120 120,160"
      fill="white" 
      stroke="red" 
      stroke-width="4"
    ></polygon>
</svg>

<path> 门路元素

<path> 元素是用来定义形态的通用元素,所有的根本形态都能够用 path 元素来创立。

其专有属性包含:

  • d 用于定义一个要绘制的门路,门路定义是一个 门路命令(下文中会介绍 组成的列表,其中的每一个命令由命令字母和用于表示命令参数的数字组成

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

门路命令

门路命令是对要绘制的门路的阐明,每一个命令由代表命令的字母和代表参数的 数字 组成,SVG 定义了六种门路命令类型,一共 20 条命令。

  • 挪动到:Mm
  • 画线至:LlHhVv
  • 三次方贝塞尔曲线:CcSs
  • 二次方贝塞尔曲线:QqTt
  • 椭圆曲线:Aa
  • 关闭门路:Zz

不难发现命令是辨别大小写的(即大小写敏感 ), 大写 的命令指定 相对坐标 小写 命令指定 绝对坐标(绝对以后地位的)。

命令中的数字能够应用 正数 模式,只不过代表的意思不同:

  • 角度 而言 正数 示意是 逆时针
  • 相对坐标 中,-x 和 -y 均示意为负坐标
  • 绝对坐标 中,-x 值为 向左 挪动,负的 -y 值为 向上 挪动

MoveTo 命令

顾名思义,就是指从 以后点 挪动到 下一点 ,即从 以后地位(Po {xo, yo}) 挪动到 新地位(Pn {xn, yn}),并且 Pn 与 Po 之间不会绘制连接线:

  • M 相对坐标,将以后地位挪动到坐标 x,y
  • m 绝对坐标,将以后地位沿 x 轴挪动 dx,沿 y 轴挪动 dy,即
    Pn = {xo + dx, yo + dy}
<svg>
    <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"
    />
</svg>

Lineto 命令

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}
<svg>
    <path
      fill="none"
      stroke="#f40"
      stroke-width="10"
      d="M 10,10
      L 100,100
      V 10
      H 30"
    />
</svg>

三次贝塞尔曲线

三次 贝塞尔曲线 是应用 四个点 定义的平滑曲线,绘制实现后 起点(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)
<svg>
    <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"
    />
</svg>

二次贝塞尔曲线

二次 贝塞尔曲线 是应用 三个点 定义的平滑曲线,绘制实现后 起点(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}
<svg>
    <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"
    />
</svg>

椭圆曲线

椭圆曲线 实际上就是用来定义为椭圆的一部分的曲线,当须要绘制 高度规定的曲线 时应用 椭圆曲线 相比于 贝塞尔曲线 会更容易:

  • 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"
    />
 </svg>

ClosePath

ClosePath 命令将从 以后地位 绘制一条 直线 到 门路中的 第一个点,其对应的命令为 Z 或 z,没有什么参数,并且大小写不敏感。

<svg stroke-width="3">
    <path
      fill="pink"
      stroke="red"
      d="M 150,50
       l -10,50 80,0
       z"
    />
</svg>

根底案例实际

因为文章篇幅无限,第一个案例会说得细一些,后续的案例就不再一一详细分析了。

环形进度条

这个应该是比拟常见的一个需要了,然而如果不让应用组件库你打算怎么实现?

要是没有理解 SVG 之前,恐怕连这么个看似简略的成果都不好实现,然而当初咱们能够借助 SVG 来实现,或者咱们先来看看组件库是怎么实现的:

以上是 ElementUi 中的实现,没错就是 SVG,当初你晓得其实你我的项目里始终都有在用 SVG 了吧!

简略剖析

  • 整体能够看成是 两个圆形 重叠,因而能够通过 <circle> 元素实现(也能够抉择 <path> 元素,如上述给出的例图)
  • <circle> 元素默认是会绘制整个圆,然而进度条必定不是一开始就是 100% 的,因而能够应用 stroke-dashoffset 属性 来将残缺的圆变成局部的,然而间接应用 stroke-dashoffset 属性是不会失效的,因为它要配合 stroke-dasharray 属性 一起来应用

    • stroke-dashoffset:指定 dash 模式 到 门路开始 的间隔
    • stroke-dasharray:管制用来描边的 点划线 的图案范式,其实你齐全能够联合 border: 1px solid dash 来了解,就是用于将一段间断的内容变成非间断的,设置了它就开启了 dash 模式

动态实现

<svg stroke-width="5">
    <!-- 背景圆形 -->
    <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>
</svg>

增加动画

通过以上的形式就实现了一个动态的环形进度条了,接下来就须要它动起来,因为 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 模式如下:

简略剖析

  • 察看整体不难发现只须要一个圆形,即应用 <circle> 元素即可
  • 其蓝色局部始终在 缩短 或 增长,这点能够通过 stroke-dasharraystroke-dashoffset 属性来实现,同时增加 transition 过渡动画即可
  • 最初是每个 缩短 或 增长 的地位不是雷同的,那么能够间接用过动画 animationroate 来实现停的旋转即可

具体实现

// html
<svg stroke-width="3">
    <circle
      cx="50"
      cy="50"
      r="20"
      fill="none"
      class="circle-loading"
    ></circle>
</svg>

// style
<style>
  .circle-loading {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: 0;
    stroke: #409eff;
    stroke-linecap: round;
    animation: loading-dash 1.5s ease-in-out infinite, 
    laoding-color 1.5s ease-in-out infinite;
  }

  @keyframes laoding-color {
    0% {stroke: #de3e35;}
    25% {stroke: #ffa500;}
    50% {stroke: #ffff00;}
    75% {stroke: #008000;}
    100% {stroke: #0000ff;}
  }

  @keyframes loading-dash {
    0% {
      stroke-dasharray: 1, 200;
      stroke-dashoffset: 0;
    }

    50% {
      stroke-dasharray: 90, 150;
      stroke-dashoffset: -40px;
    }

    to {
      stroke-dasharray: 90, 150;
      stroke-dashoffset: -120px;
    }
  }
</style>

按钮动效

简略剖析

  • 外层包裹的矩形能够通过 <rect> 元素实现
  • 矩形的线条完好不残缺,能够通过 stroke-dasharraystroke-dashoffset 属性来实现
  • 当鼠标搁置下来时,产生的动画可通过 animationstroke-dasharraystroke-dashoffset 等属性联合即可

具体实现

// html
 <svg class="svg-wrap">
    <text class="text" x="60" y="75">CLICK HERE</text>
    <rect class="rect" x="40" y="35" />
  </svg>

// style
<style>
  .svg-wrap {
    stroke-width: 3px;
    background-color: black;
  }

  .rect {
    height: 60px;
    width: 220px;
    stroke: #fff;
    fill: transparent;
    stroke-dasharray: 220 60;
    stroke-dashoffset: -260;
    stroke-width: 4px;
  }

  .text {
    fill:  #1287f4;
    font-size: 30px;
  }

  .svg-wrap:hover .rect {animation: line-move 0.5s linear forwards;}

  .svg-wrap:hover .text{
    fill:  #fff;
    transition: all 1s ease-in-out;
  }

  @keyframes line-move {
    0% {
      stroke-dasharray: 220 60;
      stroke-dashoffset: -260;
      stroke-width: 4px;
      stroke: #e32727;
    }
    to {
      stroke-dasharray: 560;
      stroke-dashoffset: 0;
      stroke-width: 2px;
      stroke: #1234f4;
    }
  }
</style>

简单案例实战

以上的根底案例因为波及的计算不多,因而咱们能够人工进行计算宽、高、偏移等等数据,然而针对简单的内容,很多参数就不是那么容易计算出来了,因而,咱们须要一些工具来疾速失去一些必要参数,而后咱们在基于这些必要参数取做批改,让其产生更丰盛的成果即可。

工具举荐

和 SVG 相干的工具就当初来说曾经遍地开花了(就如同当初的 ChatGPT、文心一言),通过搜索引擎查找都能找进去很多,这里也不谈这些工具的优劣了,上面简略列举一些:

  • figma:反对浏览器在线,反对客户端下载
  • sketch:反对浏览器在线,反对客户端下载(Mac)
  • Adobe Illustrator:反对浏览器在线,反对客户端下载
  • Pixso:号称 Sketch 的新抉择,简直还原了 Sketch 的业余性能

上面的示例都是基于 figma 来演示的,不再后续赘述。

文字动效

还是同样的第一个案例这里尽量讲具体点,后续案例就不再述说过于具体的内容了。

应用 figma 创立文字门路如下

因为文字内容的门路很难间接计算解决,因而咱们能够通过 figma 来帮忙咱们生成相应的文字门路,大抵操作如下:

解决 SVG 代码内容

失去的 SVG 内容大抵如下,代码内容比拟多这里用图片代替,其中各个内容的对应关系如下所示:

其中的 <mask> 须要去掉,否则文字的色彩值将无奈填充。

stroke-dasharray & stroke-dashoffset 属性

因为咱们须要让文字具备断续连贯的能力,这里还是得应用后面提到 stroke-dasharraystroke-dashoffset 属性来实现,它们的性能后面曾经形容过了,也用了几次了,如果你不记得了能够回过头去看看。

然而这里的 stroke-dasharraystroke-dashoffset 的值到底该设置成多少呢?

首先肯定是设置成每个文字的长度,那么问题就变成了怎么获取文字的长度了,不必放心,还记得在实现 环形进度条 时用到的 getTotalLength() 办法吗?

这里咱们依然能够应用它来获取每个文字的长度了,代码如下:

 const paths = document.querySelectorAll('path')
  for (const [ptah,index] of paths) {console.log(`path 的门路长度 = ${ptah.getTotalLength()}`)
  }
  
  输入后果:path 的门路长度 = 179.47874450683594  S
   path 的门路长度 = 150.7733917236328   V
   path 的门路长度 = 274.966064453125    G
   path 的门路长度 = 442.99505615234375  文
   path 的门路长度 = 514.3809204101562   字

接下来为每个 path 设置款式:

#svg-text > path:nth-of-type(1) {
    stroke-dasharray: 179.479;
    stroke-dashoffset: 179.479;
}
#svg-text > path:nth-of-type(2) {
    stroke-dasharray: 150.773;
    stroke-dashoffset: 150.773;
}
#svg-text > path:nth-of-type(3) {
    stroke-dasharray: 274.966;
    stroke-dashoffset: 274.966;
}
#svg-text > path:nth-of-type(4) {
    stroke-dasharray: 442.995;
    stroke-dashoffset: 442.995;
}
#svg-text > path:nth-of-type(5) {
    stroke-dasharray: 514.381;
    stroke-dashoffset: 514.381;
}

设置了这些值之后,文字内容就会不可见了,而这也是 动画的初始状态

animation 动画

后面种种操作曾经实现了动画的初始状态,接下来咱们要增加上 animation 动画,外围扭转的就是 stroke-dashoffset 的值,就是把它设置成 0,文字内容就会被从暗藏变成显示,再增加过渡工夫就实现了,反复内容就不贴出来了:

#svg-text > path:nth-of-type(1) {
    /* ... */
    animation: text-line 2s ease forwards;
}
#svg-text > path:nth-of-type(2) {
    /* ... */
    animation: text-line 2s ease forwards 300ms;
}
#svg-text > path:nth-of-type(3) {
     /* ... */
    animation: text-line 2s ease forwards 600ms;
}
#svg-text > path:nth-of-type(4) {
    /* ... */
    animation: text-line 2s ease forwards 900ms;
}
#svg-text > path:nth-of-type(5) {
    /* ... */
    animation: text-line 2s ease forwards 1200ms;
}

#svg-text{
    stroke: #d205f7;
    fill: none;
    animation: fill-color 2.5s ease-in forwards;
}

@keyframes text-line {
    to {stroke-dashoffset: 0;}
}

@keyframes fill-color{
    to{
      stroke: transparent;
      fill: #d205f7;
    }
}

反复的事交给 JavaScript

下面才 5 个文字就须要写那么多的款式,属实不能忍,于是咱们能够将反复的局部交给 JavaScript 代码去解决:

<style>
  #svg-text {
    stroke: #d205f7;
    stroke-width: 2px;
    fill: none;
    animation: fill-color 2.5s ease-in forwards;
  }

  @keyframes text-line {
    to {stroke-dashoffset: 0;}
  }

  @keyframes fill-color {
    to {
      stroke: transparent;
      fill: #d205f7;
    }
  }
</style>

<script>
    function init() {const paths = Array.from(document.querySelectorAll('path'))
        paths.forEach((path, index) => {const len = path.getTotalLength()
          path.style.strokeDasharray = len
          path.style.strokeDashoffset = len
          path.style.animation = `text-line 2.5s ease-in forwards ${index * 300}ms`
        })
    }

    init()
</script>

静止轨迹

简略剖析

实现以上成果须要包含以下几个内容:

  • 获取 指标物SVG 代码
  • 绘制 静止门路
  • 让指标物 沿着门路静止

    获取指标物的 SVG 代码

    这个能够间接从 iconfont 上抉择对应的内容,而后复制它的 SVG 代码。

绘制静止门路

静止门路的绘制咱们依然能够通过 SVG 工具 figma 来获取,值得注意的是默认的门路是用还是填充的,真正在利用时能够通过 stroke="transparent" 将门路色彩变成通明色,整体感官更好,大抵如下:

让指标物沿着门路静止

针对这种按特定静止轨迹进行的动画,也不须要你去一点点计算了,咱们能够借助 GreenSock 中的 motionpath 插件来实现,在其对应的文档中有具体的介绍,外围就是引入以下两个内容:

<div id="app">
  <!-- 鸟 -->
  <svg
    id="bird"
    t="1679665908640"
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="14202"
    width="100"
    height="100"
  >
    省略内容
  </svg>

  <!-- 门路 -->
  <svg
    width="719"
    height="419"
    viewBox="0 0 719 419"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      id="path"
      d="M1 268C146.006 483.259 245.695 450.805 336 268C518.233 -96.9549 599.902 -63.7284 718 222"
      stroke="transparent"
    />
  </svg>
</div>

<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
<script src="https://unpkg.com/gsap@3/dist/MotionPathPlugin.min.js"></script>
<script>
  // 注册插件
  gsap.registerPlugin(MotionPathPlugin);
  
  // 开启动画
  gsap.to("#bird", {
    duration: 5,
    repeat: 12,
    repeatDelay: 1,
    yoyo: true,
    ease: "power1.inOut",
    motionPath: {
      path: "#path",
      align: "#path",
      alignOrigin: [0.5, 0.5],
    },
  });
</script>

最初

欢送关注同名公众号《熊的猫》,后续文章会同步更新!

以上就是本文无关 SVG 根底局部的介绍和应用了,不晓得你是入门了,还是被门绊了一下,还是那句话:心愿本文对你所有帮忙!!!

正文完
 0