前言
其实在大部分的项目中都有 直接 或 间接 使用到 SVG 和 Canvas,但是在大多数时候我们只是选择 简单了解 或 直接跳过,这有问题吗?没有问题,毕竟砖还是要搬的
!
话说回来,前端其实还是需要对 SVG 和 Canvas 进行学习的,因为其实你一直都在用,多了解不会让你有什么损失,最基本的可以避免:
- 不至于当 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-loader
、webpakc 中的 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-color 和 background-color 属性实现的,而是通过 stroke 和 fill 来实现的:
<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> 复制代码