浅谈SVG的那些事儿

338 阅读8分钟

*作者:浮笙若有梦

开篇

image.png

轻流有一套自己的icon库,之前每个icon对应一个svg图标。这会导致一个问题:network中会有一堆的svg请求,这种多次请求会极大地增加服务器的负担,但现在项目启动后network中所有的svg请求都不见了,那么它究竟去哪里了?为了搞清楚这个问题,就需要我们掌握一些svg的知识,在文章的最后会由我带着大家来揭开这个疑问。 image.png

定义

可缩放矢量图形(Scalable Vector Graphics,svg)基于 XML 标记语言,用于描述二维的矢量图形。

相关拓展

对于计算机领域,图像一般分为两大类:矢量图和位图(也叫标量图)。

矢量图最大的特点是可以随意缩放,不论您如何改变矢量图像的大小,矢量图的质量是不会变的,因为矢量图完全由数学公式构成,图像大小不影响数学公式的表达。 常见的矢量图文件格式:

  • .dwg
  • .svg
  • .ai
  • .dxf

位图(标量图)指一个特定大小的图像。如果您放大一个位图,它会变得“像素化”并且失去之前的清晰度。这是因为位图本质上是由一组彩色的正方形组成的。 常见的位图文件格式:

  • .jpg
  • .bmp
  • .tiff
  • .gif
  • .png
  • .heif

两者的放大之后的对比图(左边:位图,右边:矢量图) image.png 可以看出,矢量图并不会因为放大而变得模糊,而这次给大家介绍的svg就是属于矢量图,对于svg的学习,大家可以理解成是一套新的标签规范,和html标签差不多。

为什么要学习它

学习 SVG 可以为前端开发人员提供创建高质量图形的能力,并为自己网站或应用程序带来更好的用户体验。

  1. 矢量图形的优势:矢量图形可以根据需要进行缩放和拉伸,而不会失去清晰度和质量。与位图不同,SVG 可以轻松地适应不同的屏幕大小和设备类型,从而使网站或应用程序更具响应性。
  2. 动画效果:SVG 允许您创建复杂的动画效果,以增强用户体验。通过使用 JavaScript 库,您可以创建酷炫的动画和交互效果,从而使您的网站或应用程序更加生动和有趣。
  3. 图标设计:SVG 可以用于创建复杂的图标和标志。这些图标和标志可以缩放到任何大小,并且可以通过 CSS 或 JavaScript 进行自定义。
  4. 可访问性:使用 SVG 可以提高网站或应用程序的可访问性。由于矢量图形可以放大,因此即使用户具有较低的视力,他们也可以轻松地看到图像的细节。

使用方法

第一种方式,也是最常用的方式就是在html中直接引入,需要注意的是SVG 代码都必须放在顶层标签之中

<!-- 在不设置svg宽高的情况下,默认宽度是300px,默认高度是150px -->
<svg>
  <circle cx="50" cy="50" r="50" fill="purple"></circle>
</svg>
<!-- 单独这样写是无法生效的 -->
<circle cx="50" cy="50" r="50" fill="purple"></circle>

第二种方式就是通过css作为背景图片引入

<style>
  .svg-container {
    width: 80px;
    height: 80px;
    background: no-repeat
      url('https://***.qingflow.com/***/6cf48d87676A9D/044206d7-a000-45f3-a381-2ba7cf19f831.svg');
    background-size: 80px 80px;
  }
</style>
<div class="svg-container"></div>

第三种方式是通过img标签的形式引入的

<!-- 直接作为图片路径引入 -->
<img
  src="https://***.qingflow.com/***/6cf48d87676A9D/044206d7-a000-45f3-a381-2ba7cf19f831.svg"
/>

剩下的方式都是不推荐的 🙅‍♂️ 🙅‍♂️ 🙅‍♂️

<!-- iframe的方式 -->
<iframe
  src="https://***.qingflow.com/***/6cf48d87676A9D/044206d7-a000-45f3-a381-2ba7cf19f831.svg"
  width="100"
  height="100"
></iframe>

<!-- embed引入  -->
<embed
  src="https://***.qingflow.com/***/6cf48d87676A9D/044206d7-a000-45f3-a381-2ba7cf19f831.svg"
  width="100"
  height="100"
/>

<!-- object引入  -->
<object
  data="https://***.qingflow.com/***/6cf48d87676A9D/044206d7-a000-45f3-a381-2ba7cf19f831.svg"
  type="image/svg+xml"
>

常用标签

矩形 rect

基础属性:

*   x: 左上角x轴坐标
*   y: 左上角y轴坐标
*   width: 宽度
*   height: 高度
*   rx:圆角,x轴的半径
*   ry:圆角

**注意点:**

1.  **默认填充色是黑色**
2.  **只设置rx或者ry其中一个是,另一个属性也是同样的值**
 

image.png

<!-- 矩形 -->
  <svg width="100" height="100" style="border: 1px solid red">
    <rect x="10" y="20" rx="0px" ry="0px" width="80" height="60"></rect>
  </svg>
圆形 circle
基础属性:

*   cx: 圆心在x轴坐标
*   cy: 圆心在y轴坐标
*   r: 半径

**注意点:**

1.  **默认填充色是黑色**

image.png

<!-- 圆形 -->
<svg width="100" height="100" style="border: 1px solid red">
  <circle cx="40" cy="40" r="30"></circle>
</svg>
椭圆 ellipse
基础属性:

*   cx: 圆心在x轴坐标
*   cy: 圆心在y轴坐标
*   rx: x轴的半径
*   ry: y轴的半径

**注意点:**

1.  **默认填充色是黑色**

image.png

<!-- 椭圆 -->
<svg width="100" height="100" style="border: 1px solid red">
  <ellipse cx="50" cy="50" rx="40" ry="20"></ellipse>
</svg>
直线 line
基础属性:

*   x1: 起点x坐标
*   y1: 起点y坐标
*   x2: 终点x坐标
*   y2: 终点y坐标
*   stroke:描边颜色

**注意点:**

1.  **默认填充色是黑色**
2.  **x1,x2是固定名字,不可以改名**
    

image.png

<!-- 直线 -->
<svg width="100" height="100" style="border: 1px solid red">
  <line x1="30" y1="40" x2="80" y2="80" stroke="purple"></line>
</svg>
折线 polyline
基础属性:

*   points: 点集
*   stroke: 描边颜色
*   fill: 填充颜色

**注意点:**

1.  **默认填充色是黑色**
2.  **points接受的是一串点集,点集是两两一组表示一个坐标(其实不用逗号隔开,用逗号是为了看得清晰)**
 

image.pngimage.png

<!-- 折线 (如果fill不设置为none,默认就会被填充) -->
<svg width="100" height="100" style="border: 1px solid red">
  <polyline points="10 10, 30 80, 60 30" stroke="#000" fill="none"></polyline>
</svg>
多边形 polygon
基础属性:

*   points: 点集
*   stroke: 描边颜色
*   fill: 填充颜色

**注意点:**

1.  **默认填充色是黑色**
2.  **polygon和polyline差不多,区别就是在于polygon会自动把起点和最后的终点连接一起来**

image.png

<!-- 多边形 -->
<svg width="100" height="100" style="border: 1px solid red">
  <polygon points="20 20, 40 80, 80 30, 40,40"></polygon>
</svg>
路径 path
基础属性:

*   d: 数据

d的关键字:

1.  M: 起始点坐标,moveto 的意思。每个路径都必须以 M 开始。M 传入 x 和 y 坐标,用逗号或者空格隔开。
2.  L: 轮廓坐标,lineto 的意思。L 是跟在 M 后面的。它也是可以传入一个或多个坐标。大写的 L 是一个绝对位置。
3.  l: 这是小写 L,和 L 的作用差不多,但 l 是一个相对位置。
4.  H: 和上一个点的Y坐标相等,是 horizontal lineto 的意思。它是一个绝对位置。
5.  h: 和 H 差不多,但 h 使用的是相对定位。
6.  V: 和上一个点的X坐标相等,是vertical lineto 的意思。它是一个绝对位置。
7.  v: 这是一个小写的 v ,和大写 V 的差不多,但小写 v 是一个相对定位。
8.  Z: 关闭当前路径,closepath 的意思。它会绘制一条直线回到当前子路径的起点。

**注意点:**

1.  **svg里面所有基本图形都是path的简写,所有描述轮廓的数据都在d里面,d是data的简写**
2.  **严格区分大小写,大小写决定着是相对坐标还是绝对坐标,但z命令不区分大小写**

image.png

<svg width="100" height="100" style="border: 1px solid red">
  <!-- 大写的L代表绝对路径 -->
  <path d="M 20 20 L 40 40 L 60 40 L 20 80" stroke="red" fill="none"></path>
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- 小写的l代表相对路径,它是会把离它最近的第一个绝对坐标都累积起来 -->
  <path d="M 20 20 l 20 20 l 20 0 l -40 40" stroke="blue" fill="none"></path>
  <!-- <path d="M 20 20 l 20 20 L 60 40 l -50 40" stroke="blue" fill="none"></path> -->
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- 大写的H代表和上一个点的纵坐标相同,只需要传入横坐标 -->
  <path d="M 20 20 L 40 40 H 60 L 20 80" stroke="orange" fill="none"></path>
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- 小写的h代表和上一个点的纵坐标相同,横坐标和上一个点相加 -->
  <path d="M 20 20 L 40 40 h 20 L 20 80" stroke="green" fill="none"></path>
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- 大写的V代表和上一个点的横坐标相同,只需要传入纵坐标 -->
  <path d="M 20 20 V 80" stroke="purple" fill="none"></path>
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- 小写的v代表和上一个点的横坐标相同,纵坐标和上一个点相加 -->
  <path d="M 20 20 v 60" stroke="gray" fill="none"></path>
</svg>
<svg width="100" height="100" style="border: 1px solid red">
  <!-- Z代表闭合路径 -->
  <path
    d="M 20 20 L 40 40 L 60 40 L 20 80 Z"
    stroke="cyan"
    fill="none"
  ></path>
</svg>
曲线 path A

绘制曲线比较抽象,一般不推荐手动绘制,可以使用一些专业软件,去生成svg

特殊标签

defs
定义:
SVG 允许我们定义以后需要重复使用的图形元素。建议把所有需要再次使用的引用元素定义在defs元素里面。这样做可以增加 SVG 内容的易读性和无障碍。在defs元素中定义的图形元素不会直接呈现。你可以在你的视口的任意地方利用 <use>元素呈现这些元素。
**作用:**
**用于定义一个svg的模版,后面通过use去调用**
注意:初始是不可见的

<svg>
  <!-- defs标签 后面需要给模版添加一个id属性 -->
  <defs>
    <circle id="container" fill="purple" cx="25" cy="25" r="30" />
  </defs>
</svg>
<svg>
  <!-- xlink:href这个地方通过指定为刚刚定义好的id来使用 -->
  <use x="50" y="20" xlink:href="#container" />
</svg>
symbol
定义:
symbol元素用来定义一个图形模板对象,它可以用一个<use>元素实例化。symbol元素对图形的作用是在同一文档中多次使用,添加结构和语义。结构丰富的文档可以更生动地呈现出来,类似讲演稿或盲文,从而提升了无障碍。注意,一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的 <use>元素)才能呈现。
**作用:**
**大致和defs作用相同,用法上面有点区别,还有一些属性是否可用的区别**
注意:初始也是不可见的

<svg>
  <!-- symbol标签 id可以直接设置在symbol标签上面 -->
  <symbol id="symbol-container">
    <circle fill="cyan" cx="25" cy="25" r="30" />
  </symbol>
</svg>
<svg>
  <use x="50" y="20" xlink:href="#symbol-container" />
</svg>
use
定义:
use元素在 SVG 文档内取得目标节点,并在别的地方复制它们。它的效果等同于这些节点被深克隆到一个不可见的 DOM 中,然后将其粘贴到use元素的位置,很像 HTML5 中的克隆模板元素。因为克隆的节点是不可见的,所以当使用CSS样式化一个use元素以及它的隐藏的后代元素的时候,必须小心注意。隐藏的、克隆的 DOM 不能保证继承 CSS 属性,除非你明文设置使用CSS 继承。
**作用:**
**可以使用defs和symbol定义过的标签**
注意:初始是不可见的

<svg>
  <!-- defs标签 -->
  <defs>
    <circle id="defs-container" fill="purple" cx="25" cy="25" r="30" />
  </defs>
</svg>
<svg>
  <!-- 使用这个定义好的标签 -->
  <use x="50" y="20" xlink:href="#defs-container" />
</svg>

<svg>
  <!-- symbol标签 -->
  <symbol id="symbol-container">
    <circle fill="cyan" cx="25" cy="25" r="30" />
  </symbol>
</svg>
<svg>
  <use x="50" y="20" xlink:href="#symbol-container" />
</svg>
g
定义:
元素g是用来组合对象的容器。添加到g元素上的变换会应用到其所有的子元素上。添加到g元素的属性会被其所有的子元素继承。此外,g元素也可以用来定义复杂的对象,之后可以通过<use>元素来引用它们。
**作用:**
**用于包含一组的svg标签,作用于g的动画或者效果以及其所有子元素都生效**

<svg>
  <!-- 四个circle属于同一个 -->
  <g stroke="green" fill="white" stroke-width="5">
    <circle cx="25" cy="25" r="15" />
    <circle cx="40" cy="25" r="15" />
    <circle cx="55" cy="25" r="15" />
    <circle cx="70" cy="25" r="15" />
  </g>
</svg>

在线链接

在线demo

终篇

image.png 现在我们对基本语法已经有个大致了解了,那么下面就是揭晓最终答案的时刻了。 首先看一下我们以前是如何使用svg的: image.png 由上图可以看出,我们是通过请求某个svg图片资源,拿到它对应的的内容,然后再手动创建一个svg,所以当页面中有大量这样的icon,每一个icon为了创建图标,就会去请求对应的svg,从而产生了大量svg的请求。 对比来看,现在我们不是请求某个svg图片,而是去通过提前声明并创建好全部的symbol标签,再通过use标签去调用,这样就能省去了请求这一步了。 image.png

最后

image.png

轻流

无代码系统搭建平台·轻流

无需代码开发即可搭建专属管理系统

帮助管理者实现管理理念的数字化转型升级

底图.png

加入我们