前言
本篇文章作为深入浅出全方位介绍SVG的功能及特性的开篇,主要介绍了什么是 SVG,SVG的发展历史及SVG的部分特性。
整个系列的知识点基本已经归纳完毕,具体大纲如下,后面会随文章的更新陆续替换成文章链接。
- 基础篇(一) - 主要介绍什么是SVG、发展历史及如何引入和使用
- 基础篇(二) - 基本图形的使用及部分容器的元素的介绍及使用
- 基础篇(三) - 纹理、裁剪、蒙版和标记及渐变
- 滤镜篇(一) - 滤镜的介绍及部分滤镜的使用
- 滤镜篇(二) - 滤镜的混合、矩阵变换、映射、光源滤镜
- 动画篇 - SMIL Animation
系列文章
什么是SVG
可缩放矢量图形,即SVG,是W3C XML的分支语言之一,用于标记可缩放的矢量图形。目前SVG在Firefox、Opera、Webkit浏览器、IE等主流浏览器中已经大部分支持。
SVG是一种XML语言,类似XHTML,可以用来绘制矢量图形。SVG可以通过定义必要的线和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来创建图形。图形和其组成部分可以形变(be transformed)、合成、或者通过滤镜完全改变外观。
SVG 的发展历史
- 1998 年 Microsoft 推出了一种基于 XML 的矢量标记语言 ( VML )
- 1999 年 2 月由 the World Wide Web 提出首个草案
- 随后的两年中提出了 6 份草案,认可和支持度不断增加
- 2003 年确定了 SVG 1.1
- 2018 年 SVG 2.0 问世
SVG 的特点。与 Canvas 的差异比较
SVG 的特点
- SVG 是一种使用 XML 描述 2D 图形的语言。
- SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。
- 在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。
Canvas 的特点
- Canvas 通过 JavaScript 来绘制 2D 图形。
- Canvas 是逐像素进行渲染的。
- 在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。
Canvas 与 SVG 的比较
- Canvas 依赖分辨率,SVG 不依赖分辨率。
- Canvas 不支持时间处理,SVG 支持事件处理
- Canvas 每次渲染都要清除画布重新渲染整块画布,SVG 只要修改对应元素的属性,渲染由浏览器自主完成
- 在图形复杂度低的情况下,SVG 与 Canvas 差不多,图形复杂的越是复杂,Canvas 的渲染速度越优于 SVG 。(因为 SVG 毕竟是 DOM ,开销大。而 Canvs 每一帧图像都是直接将绘图指令发给 GPU 进行绘制)
- Canvas 可以以 .png 或 .jpg 格式保存结果图像
SVG 兼容和当前规范
SVG 规范
目前使用的规范是 SVG 1.1 和 SVG 2.0 。SVG2.0正在制定当中,它采用了类似CSS3的制定方法,通过若干松散耦合的组件形成一套标准。
SVG 兼容性
大部分浏览器都已经支持了 SVG ,但是不同的浏览器直接依然存在使用的差异,具体可以查看 Can I use
矢量坐标与定位
与 Canvas 一样 SVG 也有它自己的画布,与 canvas 不同的是,SVG 的大小或长度是相对的。可以根据调整画布和 viewBox(视口)的比例来调整。
<h4>画布是 200*200 px,视口 200*200 </h4>
<svg class="border" width="200" height="200" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
<br/>
<h4>画布是 200*200 px,视口 400*400 </h4>
<svg class="border" width="200" height="200" viewBox="0 0 400 400">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
<br>
<h4>画布是 200*200 px,视口 400*400, 视口起始点坐标-90 -90 </h4>
<svg class="border" width="200" height="200" viewBox="-90 -90 400 400">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
<br/>
<h4>画布是 200*200 pt,视口 400*400 </h4>
<svg class="border" width="200pt" height="200pt" viewBox="0 0 400 400">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
在 200 * 200 的画布上设置 viewBox 的长宽也为200 * 200,展示一个 半径 80 的圆
<svg width="200" height="200" viewBox="0 0 200 200">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
svg 的 width 和 heigt 设置的是画布的大小。viewBox 是视口显示区域的大小。
如果一个长宽 200 的画布,显示一个长宽 400 的区域。那么显示的内容,相对与 200 的画布中的内容就小了一倍,这里由于半径小了一半,所以整体面积变为原来的 1/4
<svg width="200" height="200" viewBox="0 0 400 400">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
规定视口的起始点为(-90,-90)。则小圆就到中间去了。
<svg class="border" width="200" height="200" viewBox="-90 -90 400 400">
<circle cx="100" cy="100" r="80" fill="green" />
</svg>
为什么会变小
首先我们需要了解到 viewBox 是什么。
基本上,在 SVG 文档中的1个像素对应输出设备(比如显示屏)上的1个像素。
通过定义 viewBox 属性可以控制显示的区域( x, y, w, h)。当设置了这个属性的时候,实际上就定义了一个 SVG 坐标系,在当前 SVG 元素内定义的图形都会以这个 SVG 坐标系的基础上绘制。
- x: 起始 x 位置
- y: 起始 y 位置
- w: 视图容器的宽
- h: 视图容器的高
上文中说的画布,也就是给 SVG 定义的 width 和 height,实际上定义的是 SVG 块的设备像素,如宽 200px 高 200px。其实还可以赋值非px的单位,如 pt 等。
但是不管画布的大小多大,也不管画布的单位是什么。画布的最终的设备像素会和 viewBox 的定义值进行结合,生成一个 SVG 坐标系。可以理解为 SVG 坐标系的单位刻度在此刻确认
图一中用 200 * 200 的画布展示了 200 * 200 的大小。在 SVG 坐标系当中 1刻度单位就代表了 1 设备像素。半径 r:80, 对应 80 个刻度单位, r 对应的设备像素就 80
图二中用 200 * 200 的画布展示了 400 * 400 的大小。在 SVG 坐标系当中 1刻度单位就代表了 0.5 设备像素。半径 r:80, 还是对应 80 个刻度单位, r 对应的设备像素就 40。在画布上的结果就是面积变为原来的 1/4。
画布的大小与 viewBox 的大小关系是 SVG 可进行缩放的关键。这种映射关系被称为用户坐标系统。除了缩放之外,坐标系统还可以旋转、倾斜、翻转。默认的用户坐标系统1用户像素等于设备上的1像素(但是设备上可能会自己定义1像素到底是多大)
SVG 的引入及使用
SVG 的引入及使用有两种方式
- 文档内通过 svg 标签定义
- 引入外部 svg 文件
- 在<svg> 标签内通过<use>标签引入
- <embed> 标签引入
- <object> 标签引入
- <image> 标签引入
- <iframe> 标签引入
需要注意的是目前微信小程序无法使用 SVG, 支付宝小程序可以使用 image 标签映入 .svg 文件进行展示
embed 和 object 两者一致,这两个标签之前是为了解决浏览器兼容问题。目前现代浏览器都支持了这个两个标签。表现上都是一样的。
引入外部 svg 文件
浏览器可以直接打开 SVG 文件,但是如果你想在 HTML 展示 SVG 文件需要容器去装一下
svg 文件
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg id="ppt" t="1633915688232" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3051" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M658.58 63.94H269.26c-78.06 0-141.33 63.28-141.33 141.33v612.95c0 78.06 63.28 141.33 141.33 141.33h485.49c78.06 0 141.33-63.28 141.33-141.33V301.44c0-31.83-12.64-62.35-35.15-84.85l-117.5-117.5a120.017 120.017 0 0 0-84.85-35.15z" fill="#F98950" p-id="3052"></path><path d="M860.93 216.59l-117.5-117.5a120.001 120.001 0 0 0-61.75-32.9v131.88c0 41.87 33.94 75.81 75.81 75.81h135.37a119.93 119.93 0 0 0-31.93-57.29zM556.02 348.38H380.37c-13.25 0-24 10.75-24 24v302.74c0 13.25 10.75 24 24 24s24-10.75 24-24V595.6h151.65c68.16 0 123.61-55.45 123.61-123.61s-55.45-123.61-123.61-123.61z m0 199.22H404.37V396.38h151.65c41.69 0 75.61 33.92 75.61 75.61s-33.92 75.61-75.61 75.61z" fill="#F26C38" p-id="3053"></path><path d="M556.02 336.38H380.37c-13.25 0-24 10.75-24 24v302.74c0 13.25 10.75 24 24 24s24-10.75 24-24V583.6h151.65c68.16 0 123.61-55.45 123.61-123.61s-55.45-123.61-123.61-123.61z m0 199.22H404.37V384.38h151.65c41.69 0 75.61 33.92 75.61 75.61s-33.92 75.61-75.61 75.61z" fill="#FFFFFF" p-id="3054"></path></svg>
- 在 svg 标签内通过 use 标签去引入
<!-- 用这个方法引入的话需要给 PPT.svg 的 svg 标签上绑定一个id,不然拿不到 -->
<svg width="200" height="200" viewBox="0 0 200 200" >
<use xlink:href="../static/PPT.svg#ppt" />
</svg>
- embed 标签
<embed
src="../static/PPT.svg"
width="300"
height="100"
type="image/svg+xml"
/>
<!-- svg 格式会随容器自适应大小 -->
<embed
src="../static/PPT.svg"
width="300"
height="200"
type="image/svg+xml"
/>
- object 标签 (不推荐)
<object
data="../static/PPT.svg"
width="300"
height="100"
type="image/svg+xml"
></object>
<!-- svg 格式会随容器自适应大小 -->
<object
data="../static/PPT.svg"
width="300"
height="200"
type="image/svg+xml"
></object>
- img 标签
<img src="../static/PPT.svg" width="300" height="100" alt="">
<!-- svg 格式会随容器自适应大小 -->
<img src="../static/PPT.svg" width="300" height="200" alt="">
- iframe 标签(不推荐)
<!--内容不会随容器自适应,超出部分以滚动条的方式展示 -->
<iframe src="../static/PPT.svg" width="300" height="100"> </iframe>
<iframe src="../static/PPT.svg" width="300" height="200"> </iframe>
写在最后
如果有出现问题或者错误,还望指正。我会尽快把全部内容更新完毕。
参考资料