上篇文章我介绍了怎么创立和运用 svg, 本文将进一步介绍怎么运用 svg 制作如下所示的图形,及相关知识点。(之后的文章会以这次制作的静态图形为基础完成 MG 动画作用)
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
,并让 width
为 100%
以完成 svg 内容能够跟从页面巨细自适应缩放(假如你不清楚原理能够去看看关于 viewBox 的介绍)。
制作十字形
下面开始制作坐落图形中间的十字形。直接在 <svg>
里运用对应的元素,就能生成相应的图形,然后能够经过特点来界说图形的位置和巨细色彩等。比方十字形我运用的是 <line>
来生成两根交叉的线条,特点 x1
、y1
和 x2
、y2
用来界说线条的两个端点坐标。
组合元素的容器 <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>
十字作用如下:
运用 css
在 SVG 中,有些特点,像 stroke-width
、stroke
等归于 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>
的款式优先级高于经过元素特点界说的款式:
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>
中的:
还能够直接在元素上经过 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>
作用如下:
咱们以坐落十字下方的紫色小半圆的制作为例,解说 <path>
的用法。它有一个根本特点 d
,用来设置途径点的位置,d
的值是 “指令 + 参数” 的序列,指令都是区别巨细写的,大写代表绝对定位,小写表明从上一个点开始核算的相对定位:
- 其必须以
M
(Move To) 指令开头,指示解析器从哪个点开始制作,M 400 328
即表明先移动到 (400, 328) 这个点,也便是圆弧的起点; -
A 28 28 0 1 1 400 272
,A
指令为弧形指令,有 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;
-
fill
作为通用的特点,给画好的半圆填充色彩,否则默许填充为黑色。
d
特点支持的指令还有许多,比方制作水平线的 H/h
等,从阿里图标库下载的图标,简直都是运用 <path>
制作,能够看出 <path>
的强壮。
制作矩形
现在来制作坐落圆形上下两头的 4 个小正方形:
界说重复元素 <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>
来制作,width
和 height
界说了宽高,蓝色正方形为实心的,所以用 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>
引证时经过 x
、y
设置位置,href
的值为引证目标的 id 或 url。<defs>
里除了能够界说根本图形,也能够界说组合图形(<g>
)或是款式(<style>
)等。在 <use>
上设置特点 width
和 height
是无效的,除非引证的元素具有 viewBox
特点,比方是另一个 <svg>
或是下面介绍的 <symbol>
元素。
symbol 元素
这儿顺便介绍下和 <defs>
相似的 <symbol>
。<defs>
元素本身是没有专有特点的,运用时一般也不会添加特点。而 <symbol>
则提供了 viewBox
、x
、y
、width
和 height
等特点:
<!-- 代码片段 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 引证的方法来运用:
制作三角形
我运用前面介绍过的 <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>
至此,图形制作成果如下:
剪切
接着制作如下图箭头所指的具有剪切作用的 4 个小三角形:
先在 <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>
内归为一组:
然后经过给形变特点 transform
赋值 rotate(45, 337, 195)
,使得它们一同顺时针旋转了 45,旋转中心点坐标为 (337, 195):
再在外面包裹上一个 <g>
,经过 clip-path
引证代码片段 1.5 界说好的三角形作为剪切概括并运用 fill
上色:
制作圆形
制作坐落四周的小圆比较简单,在 <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>
经过 x
,y
界说图片位置,假如不写则值默许为 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 制作的代码,这也就利于 SEO:
当然 svg 也有缺陷,比方当 svg 很复杂时,DOM 变得复杂,烘托就会变得比较慢。