上篇文章我介绍了怎么创立和运用 svg, 本文将进一步介绍怎么运用 svg 制作如下所示的图形,及相关知识点。(之后的文章会以这次制作的静态图形为基础完成 MG 动画作用)

svg 绘图

svg 元素

本事例挑选直接在 html 中运用 <svg> 元素来制作图形:

<!-- 代码片段 1 -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      svg {
        border: 1px solid red;
      }
    </style>
  </head>
  <body>
    <!-- 界说 svg -->
    <svg width="100%" height="600" viewBox="0 0 800 600">
      <!-- 制作内容 -->
    </svg>
  </body>
</html>

在代码片段 1 中,我经过给 <svg> 设置 viewBox,并让 width100% 以完成 svg 内容能够跟从页面巨细自适应缩放(假如你不清楚原理能够去看看关于 viewBox 的介绍)。

制作十字形

下面开始制作坐落图形中间的十字形。直接在 <svg> 里运用对应的元素,就能生成相应的图形,然后能够经过特点来界说图形的位置和巨细色彩等。比方十字形我运用的是 <line> 来生成两根交叉的线条,特点 x1y1x2y2 用来界说线条的两个端点坐标。

组合元素的容器 <g>

由于两根线条的线宽 stroke-width 和色彩 stroke 是相同的,所以我把相同的特点界说在了用来组合元素的容器 <g> 元素上,然后让作为其子元素的 <line> 承继:

<!-- 代码片段 1.1 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <!-- 十字 -->
  <g stroke-width="8" stroke="#FAB748">
    <!-- 横 -->
    <line x1="380" y1="300" x2="420" y2="300"></line>
    <!-- 竖 -->
    <line x1="400" y1="280" x2="400" y2="320"></line>
  </g>
</svg>

十字作用如下:

svg 绘图

运用 css

在 SVG 中,有些特点,像 stroke-widthstroke 等归于 Presentation Attributes,除了能够直接在元素上经过特点界说,还能够直接运用 css 设置,比方:

<!-- 代码片段 1.1.1 -->
<style>
  .cross {
    stroke-width: 8;
    stroke: red;
  }
</style>
</head>
<body>
  <svg width="100%" height="600" viewBox="0 0 800 600">
    <g class="cross" stroke-width="8" stroke="#FAB748">
      <!-- 省掉 -->
    </g>
  </svg>
</body>

得到的会是一个红色的十字,阐明界说在 <head> 里的 <style> 的款式优先级高于经过元素特点界说的款式:

svg 绘图

css 也能够界说在之后会介绍的 <defs> 中:

<!-- 代码片段 1.1.2 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <defs>
    <style>
      .cross {
        stroke: skyblue;
      }
    </style>
  </defs>
  <!-- 十字 -->
  <g class="cross" stroke-width="8" stroke="#FAB748">
    <!-- 省掉 -->
  </g>
</svg>

这样得到的便是蓝色十字,而且界说在 <defs> 里的 <style> 的优先级高于界说在 <head> 中的:

svg 绘图

还能够直接在元素上经过 style 界说,而且优先级最高:

<!-- 代码片段 1.1.3 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <!-- 十字 -->
  <g style="stroke: goldenrod" stroke-width="8">
    <!-- 省掉 -->
  </g>
</svg>

制作半圆

制作半圆的办法不止一种,我挑选的是直接运用途径元素 <path>。为了让半圆坐落十字的下方,咱们需求在界说十字的前面界说好半圆:

<!-- 代码片段 1.2 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <!-- 中间的圆 -->
  <!-- 紫色大半圆 -->
  <path d="M 400 384 A 84 84 0 1 0 400 216" fill="#8052E8"></path>
  <!-- 蓝色大半圆 -->
  <path d="M 400 384 A 84 84 0 1 1 400 216" fill="#26AAD6"></path>
  <!-- 紫色小半圆 -->
  <path d="M 400 328 A 28 28 0 1 1 400 272" fill="#8052E8"></path>
  <!-- 蓝色小半圆 -->
  <path d="M 400 328 A 28 28 0 1 0 400 272" fill="#26AAD6"></path>
  <!-- 十字 -->
</svg>

作用如下:

svg 绘图

咱们以坐落十字下方的紫色小半圆的制作为例,解说 <path> 的用法。它有一个根本特点 d,用来设置途径点的位置,d 的值是 “指令 + 参数” 的序列,指令都是区别巨细写的,大写代表绝对定位,小写表明从上一个点开始核算的相对定位:

  • 其必须以 M(Move To) 指令开头,指示解析器从哪个点开始制作,M 400 328 即表明先移动到 (400, 328) 这个点,也便是圆弧的起点;
  • A 28 28 0 1 1 400 272A 指令为弧形指令,有 7 个参数:
    • 前 2 个参数分别是 x 轴半径(rx)和 y 轴半径(ry),由于是半圆,所以应该是相等的,我设置为 28;
    • 第 3 个参数为旋转视点(x-axis-rotation,值为正数时顺时针旋转),当 rx 和 ry 相等时设置无效,所以为 0;
    • 第 4 个参数(large-arc-flag)有两个可选值,0 代表取小视点弧线,1 代表取大视点弧线;
    • 第 5 个参数(sweep-flag)也是有两个可选值,0 代表逆时针,1 代表顺时针;
    • 最终 2 个参数为圆弧结尾的 x、y 坐标,由于起点在 (400, 328),半径为 28,所以结尾 x 为 400,y 为 328 – 28 * 2 = 272;

svg 绘图

  • fill 作为通用的特点,给画好的半圆填充色彩,否则默许填充为黑色。

d 特点支持的指令还有许多,比方制作水平线的 H/h 等,从阿里图标库下载的图标,简直都是运用 <path> 制作,能够看出 <path> 的强壮。

制作矩形

现在来制作坐落圆形上下两头的 4 个小正方形:

svg 绘图

界说重复元素 <defs>

能够看到,假如咱们制作好了一端的小正方形,在另一端只需求改一下定位是能够复用的,所以咱们在 <defs> 内界说好正方形:

<!-- 代码片段 1.3 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <defs>
    <!-- 蓝色正方形 -->
    <rect id="blueRect" width="42" height="42" fill="#26AAD6"></rect>
    <!-- 绿色正方形 -->
    <rect
      id="greenRect"
      width="34"
      height="34"
      fill="none"
      stroke-width="8"
      stroke="#51E88D"
      ></rect>
  </defs>
  <!-- 省掉 -->
</svg>

正方形运用制作矩形的 <rect> 来制作,widthheight 界说了宽高,蓝色正方形为实心的,所以用 fill 填充,绿色正方形为空心的,所以运用 stroke 描边。

引证元素 <use>

<defs> 里界说的可复用元素是看不到的,需求运用 <use> 来引证并显现:

<!-- 代码片段 1.3.1 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <defs>
    <!-- 界说正方形 -->
  </defs>
  <!-- 显现正方形 -->
  <!-- 左上角蓝色 x = 400 - 42; y = 300 - 84 - 42  -->
  <use x="358" y="174" href="#blueRect"></use>
  <!-- 右下角蓝色 x = 400; y = 300 + 84 -->
  <use x="400" y="384" href="#blueRect"></use>
  <!-- 右上角绿色 x = 400 + 4; y = 300 - 84 - (42 - 4) -->
  <use x="404" y="178" href="#greenRect"></use>
  <!-- 左下角绿色 x = 400 - 42 + 4; y = 300 + 84 + 4 -->
  <use x="362" y="388" href="#greenRect"></use>
</svg>

引证时经过 xy 设置位置,href 的值为引证目标的 id 或 url。<defs> 里除了能够界说根本图形,也能够界说组合图形(<g>)或是款式(<style>)等。在 <use> 上设置特点 widthheight是无效的,除非引证的元素具有 viewBox 特点,比方是另一个 <svg> 或是下面介绍的 <symbol> 元素。

symbol 元素

这儿顺便介绍下和 <defs> 相似的 <symbol><defs> 元素本身是没有专有特点的,运用时一般也不会添加特点。而 <symbol> 则提供了 viewBoxxywidthheight 等特点:

<!-- 代码片段 1.3.2 -->
<body>
  <svg>
    <symbol id="myRect" viewBox="0 0 100 100">
      <rect width="100" height="100"></rect>
    </symbol>
  </svg>
  <svg>
    <use href="#myRect" width="50" height="50"></use>
  </svg>
  <svg width="50" height="50">
    <use href="#myRect"></use>
  </svg>
</body>

通常是在一个 <svg> 内运用 <symbol> 界说好要复用的内容,这些内容不会显现。然后在别的 <svg> 内运用 <use> 引证并显现,而且能够经过给 <svg><use> 设置宽高来完成对复用图形的缩放。 <symbol> 常见的运用场景是界说图标,比方阿里图标库的图标就能够经过 symbol 引证的方法来运用:

svg 绘图

制作三角形

我运用前面介绍过的 <path> 制作坐落中心圆两侧的三角形,用到了 2 个新指令:

  • l(Line to)用于制作线段,其参数便是线段结尾的坐标,由于是小写的,所以采用的是相对定位;
  • Z 用于闭合途径,即从当时点制作一条直线到途径起点,不区别巨细写。
<!-- 代码片段 1.4 -->
<svg width="100%" height="600" viewBox="0 0 800 600">
  <!-- 省掉 -->
  <!-- 亮黄色三角形 -->
  <g fill="#FFED5D">
    <!-- 左 -->
    <path d="M 316 300 l 0 -84 l -84 84 Z"></path>
    <!-- 右 -->
    <path d="M 484 300 l 0 84 l 84 -84 Z"></path>
  </g>
  <!-- 橘色三角形 -->
  <g fill="#FAB748">
    <!-- 左 -->
    <path d="M 316 300 l 0 84 l -84 -84 Z"></path>
    <!-- 右 -->
    <path d="M 484 300 l 0 -84 l 84 84 Z"></path>
  </g>
</svg>

至此,图形制作成果如下:

svg 绘图

剪切

接着制作如下图箭头所指的具有剪切作用的 4 个小三角形:

svg 绘图

先在 <defs> 内运用 <clipPath> 界说好作为剪切概括的三角形,此处三角形的制作采用的是用于制作多边形的 <polygon>,它的特点 points 的值为各个点的坐标,最终一个点会主动与第一个点连线闭合:

<!-- 代码片段 1.5 -->
<defs>
  <!-- 用于剪切的三角形 -->
  <!-- 左上 -->
  <clipPath id="cut-off-left-top">
    <polygon points="316 216, 358 216, 358 174" />
  </clipPath>
  <!-- 右上 -->
  <clipPath id="cut-off-right-top">
    <polygon points="442 216, 484 216, 442 174" />
  </clipPath>
  <!-- 左下 -->
  <clipPath id="cut-off-left-bottom">
    <polygon points="316 384, 358 384, 358 426" />
  </clipPath>
  <!-- 右下 -->
  <clipPath id="cut-off-right-bottom">
    <polygon points="442 384, 484 384, 442 426" />
  </clipPath>
</defs>

然后以左上角的小剪切三角形为例阐明怎么运用剪切图形:

<!-- 代码片段 1.5.1 -->
<!-- 左上角剪切三角 -->
<g clip-path="url(#cut-off-left-top)" fill="#FAB748">
  <g transform="rotate(45, 337, 195)">
    <rect x="316" y="162" width="50" height="6"></rect>
    <rect x="316" y="174" width="50" height="6"></rect>
    <rect x="316" y="186" width="50" height="6"></rect>
    <rect x="316" y="198" width="50" height="6"></rect>
    <rect x="316" y="210" width="50" height="6"></rect>
    <rect x="316" y="222" width="50" height="6"></rect>
  </g>
</g>

我运用 <rect> 界说了多个矩形,并把它们放入 <g> 内归为一组:

svg 绘图

然后经过给形变特点 transform 赋值 rotate(45, 337, 195),使得它们一同顺时针旋转了 45,旋转中心点坐标为 (337, 195):

svg 绘图

再在外面包裹上一个 <g>,经过 clip-path 引证代码片段 1.5 界说好的三角形作为剪切概括并运用 fill 上色:

svg 绘图

制作圆形

制作坐落四周的小圆比较简单,在 <defs> 内运用 <circle> 界说好圆形,r 为半径:

<!-- 代码片段 1.6 -->
<defs>
  <!-- 四个角的蓝色圆 -->
  <circle id="blueCircle" r="20" fill="#26AAD6"></circle>
</defs>

然后进行引证:

<!-- 代码片段 1.6.1 -->
<!-- 四周小圆 -->
<!-- 左上 x = 400 - 84 - 84; y = 300 - 84 - 84 -->
<use x="232" y="132" href="#blueCircle"></use>
<!-- 左下 y = 300 + 84 + 84 -->
<use x="232" y="468" href="#blueCircle"></use>
<!-- 右上 x = 400 + 168 -->
<use x="568" y="132" href="#blueCircle"></use>
<!-- 右下 -->
<use x="568" y="468" href="#blueCircle"></use>

制作图片

运用 <image> 元素制作图片,注意是经过 href 特点引证,而不是像 html 中的 <img> 运用 src

<!-- 代码片段 1.7 -->
<image x="214" y="286" href="../imgs/juejin.png" width="40"></image>

经过 xy 界说图片位置,假如不写则值默许为 0;width 指定图片的宽度,高度会依照图片原宽高比主动调整,假如宽高均不设置则默许为原图巨细。

制作文字

最终在右下角运用 <text> 签个名,在 <text> 内还能够运用 <tspan> 对部分文字设置单独的款式:

<!-- 代码片段 1.8 -->
<text x="600" y="580" font-size="12" fill="#26AAD6">
  by:
  <tspan font-size="14">亦黑迷失</tspan>
</text>

SVG 的优缺陷

至此,制作完毕。回忆制作过程,不难发现 svg 的优点有许多,比方制作都是声明式地直接运用对应的元素,而且能够经过 css 和 js 修正,也就更利于创立动画。放大浏览器的页面缩放比例,能够看到图形并不会像运用 canvas 制作的图形那样呈现失真:

svg 绘图

检查源代码,能够看到一切运用 svg 制作的代码,这也就利于 SEO:

svg 绘图

当然 svg 也有缺陷,比方当 svg 很复杂时,DOM 变得复杂,烘托就会变得比较慢。

svg 绘图
svg 绘图