[译] 深刻浅出 SVG

深刻浅出 SVG

SVG 是优秀且使人难以置信的强大图像格式。本教程经过简单地解释全部须要了解的知识,为您提供 SVG 的概述。css

介绍

尽管在 21 世纪初被标准化了,SVG(Scalable Vector Graphics 的缩写)是近年来的一个热门话题。html

SVG 已经被糟糕的浏览器支持(尤为是 IE)惩罚了好多年。前端

我发现这话源自一本 2011 的书:在撰写本文时,只有在最新的浏览器中才能将 SVG 直接嵌入到 HTML 中工做。7 年过去了,这句话如今已是过去式了,咱们能够很安全地使用 SVG 图像。android

如今咱们能够安全地使用 SVG 图像,除非您有不少用户使用 IE8 以及更低版本,或者使用较旧的 Android 设备。这种状况下,依然存在着备选方案。ios

SVG 支持的浏览器

SVG 成功的一部分是因为咱们必须支持各类不一样分辨率和尺寸的屏幕显示。SVG 能完美解决这个问题。git

同时,Flash 在过去几年的迅速衰退致使你们对 SVG 产生了兴趣。这对于 Flash 过去所作的许多事情都是很是重要的。github

SVG 是一种 vector 图像文件格式。这使得它们与其余图像格式(如 PNG、GIF 或 JPG)有很大的不一样,后者是光栅图像文件格式。web

SVG 的优点

因为 SVG 图像是矢量图像,能够无限缩放,并且在图像质量降低方面没有任何问题。为何会这样呢?由于 SVG 图像是使用 XML 标记构建的,浏览器经过绘制每一个点和线来打印它们,而不是用预约义的像素填充某些空间。这确保 SVG 图像能够适应不一样的屏幕大小和分辨率,即便是那些还没有发明的。后端

因为是在 XML 中定义的,SVG 图像比 JPG 或 PNG 图像更灵活,并且咱们可使用 CSS 和 JavaScript 与它们进行交互。SVG 图像设置能够包含 CSS 和 JavaScript。api

SVG 能够渲染比其余格式小得多的矢量风格图像,主要用于标识和插图。另外一个巨大的用例是图标。曾经是图标字体域,好比 FontAwesome,如今的设计师更喜欢使用 SVG 图像,由于它更小,而且容许使用多色图标。

SVG 在动画方面很简单,这是一个很是酷的话题。

SVG 提供了一些图像编辑效果,好比屏蔽和剪裁、应用过滤器等等。

SVG 只是文本,所以可使用 GZip 对其进行有效压缩。

您的第一个 SVG 图像

SVG 图像使用 XML 定义,这意味着若是您精通 HTML,SVG 看起来会很是熟悉,除了在 SVG 中有标签适合文档构建(如 particlefooteraside)咱们还有矢量图的构建块: pathrectline 等等。

这是一个 SVG 图像示例:

<svg width="10" height="10">
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>
复制代码

注意它很是容易阅读和理解图像的样子:它是一个 10 x 10 像素的简单蓝色矩形(默认单元)。

大多状况下,您没必要编写 SVG 代码,由于您可使用 Sketch 或 Figma 等工具或任何其余矢量图形工具来建立图像,并将其导出为 SVG。

SVG 的当前版本是 1.1, SVG 2.0 正在研发。

使用 SVG

浏览器能够经过将它们包含在一个 img 标签中来显示 SVG 图像:

<img src="image.svg" alt="My SVG image" />
复制代码

就像其余基于像素的图像格式同样:

<img src="image.png" alt="My PNG image" />
<img src="image.jpg" alt="My JPG image" />
<img src="image.gif" alt="My GIF image" />
<img src="image.webp" alt="My WebP image" />
复制代码

此外,SVG 很是独特,它们能够直接包含在 HTML 页面中:

<!DOCTYPE html>
<html>
  <head>
    <title>A page</title>
  </head>
  <body>
    <svg width="10" height="10">
      <rect x="0" y="0" width="10" height="10" fill="blue" />
    </svg>
  </body>
</html>
复制代码

请注意 HTML5 和 XHTML 对于内联 SVG 图像须要不一样的语法。幸运的是,XHTML已是过去的事情了,由于它过于繁杂,可是若是您仍然须要处理 XHTML 页面,就值得去了解它。

在 HTLM 中内联 SVG 的功能使该格式成为场景中的 unicorn,由于其余图像不能这样作,必须为每一个图像打开一个单独的请求来获取该格式。

SVG 元素

在上面的示例中,您看到了 rect 元素的用法。SVG 有许多不一样的元素。

最经常使用的是

  • text: 建立一个 text 元素
  • circle: 建立一个圆
  • rect: 建立一个矩形
  • line: 建立一条线
  • path: 在两点之间建立一条路径
  • textPath: 在两点之间建立一条路径,并建立一个连接文本元素
  • polygon: 容许建立任意类型的多边形
  • g: 单独的元素

坐标从绘图区域左上角的 0,0 开始,并 从左到右表示 x, 从上到下表示 y

您看到的图像反映了上面所示的代码。使用浏览器 DevTools,您能够检查和更改它们。

text

text 元素添加文本。可使用鼠标选择文本。xy 定义文本的起始点。

<svg>
  <text x="5" y="30">A nice rectangle</text>
</svg>
复制代码
漂亮的长方形

circle

定义圆。 cxcy 是中心坐标,r 是半径。 fill 是一个经常使用属性,表示图形颜色。

<svg>
  <circle cx="50" cy="50" r="50" fill="#529fca" />
</svg>
复制代码

rect

定义矩形。 xy 是起始坐标,widthheight 是自解释的。

<svg>
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
</svg>
复制代码

line

x1y1 定义起始坐标。x2y2 定义结束坐标。stroke 是一个经常使用属性,表示线条颜色。

<svg>
  <line x1="0" y1="0" x2="100" y2="100" stroke="#529fca" />
</svg>
复制代码

path

路径是一系列的直线和曲线。它是全部 SVG 绘制工具中最强大的,所以也是最复杂的。

d 包含方向命令。这些命令以命令名和一组坐标开始:

  • M 表示移动,它接受一组 x,y 坐标
  • L 表示直线将绘制到它接受一组 x,y
  • H 是一条水平线,它只接受 x 坐标
  • V 是一条垂直线,它只接受 y 坐标
  • Z 表示关闭路径,并将其放回起始位置
  • A 表示 Arch,它本身须要一个完整的教程
  • Q 是一条二次 Bezier 曲线,一样,它本身也须要一个完整的教程
<svg height="300" width="300">
  <path d="M 100 100 L 200 200 H 10 V 40 H 70"
        fill="#59fa81" stroke="#d85b49" stroke-width="3" />
</svg>
复制代码

textPath

沿路径元素的形状添加文本。

Wow such a nice SVG tut

polygon

使用 polygon 绘制任意多边形。 points 表明一组 x,y 坐标多边形应该连接:

<svg>
  <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" />
</svg>
复制代码

g

使用 g 元素,您能够对多个元素进行分组:

<svg width="200" height="200">
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
  <g id="my-group">
    <rect x="0" y="100" width="100" height="100" fill="#59fa81" />
    <rect x="100" y="0" width="100" height="100" fill="#59fa81" />
  </g>
</svg>
复制代码

SVG viewport 和 viewBox

SVG 相对于其容器的大小由 svg 元素的 widthheight 属性设置。这些单位默认为像素,但您可使用任何其余经常使用单位,如 %em。这是 viewport

一般 “container” 指的是浏览器窗口,但 svg 元素能够包含其余 svg 元素,在这种状况下,容器是父元素 svg

一个重要的属性是 viewBox。它容许您在 SVG 画布中定义一个新的坐标系统。

假设在 200x200px SVG 中有一个简单的圆:

<svg width="200" height="200">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
复制代码

经过指定 viewBox ,您能够选择 只显示此 SVG 的一部分。例如,您能够从 0,0 点开始,只显示一个 100 x 100 px 画布:

<svg width="200" height="200" viewBox="0 0 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
复制代码

从 100,100 开始,您会看到另外一部分,圆圈的右下角:

<svg width="200" height="200" viewBox="100 100 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
复制代码

一个很好的可视化方法是想象 Google Maps 是一个巨大的 SVG 图像,而您的浏览器是一个和窗口大小同样大的视图框。当您移动时,Viewbox 会更改它的起始点(x,y)坐标,而且当您调整窗口的大小时,会更改 Viewbox 的宽度和高度。

在 Web 网页中插入 SVG

将 SVG 添加到网页中有多种方法。

最多见的是:

  • 带有 img 标签
  • 带有 CSS background-image 属性
  • 在 HTML 中内联
  • 带有 objectiframeembed 标签

在 Glitch 上能够查看这些示例 flavio-svg-loading-ways.glitch.me/

带有 img 标签

<img src="flag.svg" alt="Flag" />
复制代码

带有 css background-image 属性

<style>
.svg-background {
  background-image: url(flag.svg);
  height: 200px;
  width: 300px;
}
</style>
<div class="svg-background"></div>
复制代码

在 HTML 中内联

<svg width="300" height="200" viewBox="0 0 300 200"
    version="1.1" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Italian Flag</title>
  <desc>By Flavio Copes https://flaviocopes.com</desc>
  <g id="flag">
      <rect fill="green" x="0" y="0" width="100" height="200"></rect>
      <rect fill="white" x="100" y="0" width="100" height="200"></rect>
      <rect fill="red" x="200" y="0" width="100" height="200"></rect>
  </g>
</svg>
复制代码

带有 objectiframeembed 标签

<object data="flag.svg" type="image/svg+xml"></object>

<iframe src="flag.svg" frameborder="0"></iframe>

<embed src="flag.svg" type="" />
复制代码

使用 embed,您可使用如下命令从父文档获取 SVG 文档

document.getElementById('my-svg-embed').getSVGDocument()
复制代码

在 SVG 内部,您能够经过如下方式引用父文档:

window.parent.document
复制代码

使用数据 URL 内联 SVG

您可使用以上任何示例结合 Data URLs 将 SVG 内联到 HTML 中:

<img src="data:image/svg+xml;<DATA>" alt="Flag" />

<object data="data:image/svg+xml;<DATA>" type="image/svg+xml"></object>

<iframe data="data:image/svg+xml;<DATA>" frameborder="0"></iframe>
复制代码

在 CSS 中也是:

.svg-background {
  background-image: url("data:image/svg+xml;<DATA>");
}
复制代码

只需使用适当的Data URL 更改<DATA>

样式元素

任何 SVG 元素均可以接受 style 属性,就像 HTML标签同样。并不是全部的 CSS 属性都能像您预期的那样工做。例如,要更改文本元素的颜色,请使用 fill 而不是 color

<svg>
  <text x="5" y="30" style="fill: green">A nice text</text>
</svg>

<svg>
  <text x="5" y="70" style="fill: green; font-family: Courier New">
    A nice text
  </text>
</svg>
复制代码

您也可使用 fill 做为元素属性,正如您在前面看到的那样:

<svg>
  <text x="5" y="70" fill="green">A nice text</text>
</svg>
复制代码

其余公共属性包括

  • fill-opacity,背景颜色不透明度
  • stroke,定义边框颜色
  • stroke-width,设置边框宽度

CSS 能够针对 SVG 元素,就像您以 HTML 标签为目标同样:

rect {
  fill: red;
}
circle {
  fill: blue;
}
复制代码

使用 CSS 或 JavaSCript 与 SVG 交互

SVG 图像可使用 CSS 进行样式化,或者使用 JavaScript 编写脚本,这种状况下:

  • 当 SVG 在 HTML 中内联
  • 经过 objectembediframe 标签加载图像时

可是 (⚠️ 取决于浏览器实现) 它们必须从相同的域(和协议)加载,这是同源策略所致使的。 iframe 须要显式定义的尺寸,不然内容将被裁剪,同时调整 objectembed 尺寸以适应其内容。.

若是 SVG 是使用 img 标签加载的,或者使用 CSS 做为背景,则与源无关:

  • CSS 和 JavaScript 不能与之进行交互
  • SVG 中包含的 JavaScript 被禁用
  • 没法从外部加载资源(如图像、样式表、脚本、字体)

细节


特性 SVG 内联 object/embed/iframe img
能够与用户交互
支持动画
能够运行 JavaScript 脚本 👎🏼
能够从外部编写脚本 👎🏼 👎🏼

内联 SVG 图像无疑是最强大和最灵活的,它是使用 SVG 执行某些操做的惟一方法。

若是您想要 SVG 与您的脚本进行任何交互,它必须之内联的方式加载到 HTML中

若是您不须要与 SVG 交互,只需在页面中显示它,将 SVG 加载至 imgobject 或者 embed 中便可,若是您在不一样的页面中重用 SVG 图像,或者 SVG 图像的大小至关大,那么加载 SVG 就特别方便。

CSS 嵌入 SVG

将 CSS 加至 CDATA:

<svg>
  <style>
    <![CDATA[
      #my-rect { fill: blue; }
    ]]>
  </style>
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>
复制代码

SVG 文件还能够包括外部样式表

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width=".." height=".." viewBox="..">
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>
复制代码

JavaScript 嵌入 SVG

你能够将 JavaScript 放在第一个位置上,并包装在一个 load 事件中,以便在页面彻底加载并在 DOM 中插入 SVG 时执行它:

<svg>
  <script>
    <![CDATA[
      window.addEventListener("load", () => {
        //...
      }, false)
    ]]>
  </script>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>
复制代码

或者若是您将 JS 放在其余 SVG 代码的末尾,能够避免添加事件监听,确保当 SVG 出如今页面时 JavaSCript 会执行。

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
  <script>
    <![CDATA[
      //...
    ]]>
  </script>
</svg>
复制代码

与 HTML 元素同样,SVG 元素也能够有 idclass 属性,所以咱们可使用 Selectors API 来引用它们:

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" class="a-rect" />
  <script>
    <![CDATA[
      console.log(document.getElementsByTagName('rect'))
      console.log(document.getElementById('my-rect'))
      console.log(document.querySelector('.a-rect'))
      console.log(document.querySelectorAll('.a-rect'))
    ]]>
  </script>
</svg>
复制代码

请查看此故障 flaviocopes-svg-script.glitch.me/ 以得到功能性提示。

SVG 外部的 JavaScript

若是能够与 SVG 交互(SVG 在 HTML 中是内联的),则可使用 JavaScript 更改任何 SVG 属性,例如:

document.getElementById("my-svg-rect").setAttribute("fill", "black")
复制代码

或者真正地作任何您想要的 DOM 操做。

SVG 外部的 CSS

您可使用 CSS 更改 SVG 图像的任何样式。

SVG 属性能够很容易地在 CSS中 被覆盖,而且它们比 CSS 具备更低的优先级。它们的行为不像具备更高优先级的内联 CSS。

<style>
  #my-rect {
    fill: red
  }
</style>
<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" />
</svg>
复制代码

SVG vs Canvas API

Canvas API 是 Web 平台一个很好的补充,它有相似于 SVG 的浏览器支持。与 SVG 主要的(也是最大的)不一样之处是:画布不是基于矢量的,而是基于像素的,因此

  • 它具备与基于像素的 png、jpg 和 gif 图像格式相同的缩放问题。
  • 这使得不可能像使用 SVG 那样使用 CSS 或 JavaScropt 编辑画布图像。

SVG 符号

符号使您能够定义一次SVG图像,并在多个地方重用它。若是您须要重用一个图像,这是一个很大的帮助,可能只是改变一点它的一些属性。

您能够经过添加一个 symbol 元素并分配一个 id 属性来完成此操做:

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="rgb(255,159,0)" />
  </symbol>
</svg>
复制代码
<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>
复制代码

(xlink:href 用于 Safari 支持,即便它是一个已废弃的属性)

这让咱们能开始了解 SVG 的强大功能。

若是您但愿对这两个矩形使用不一样的样式,例如,对每一个矩形使用不一样的颜色?您可使用CSS 变量.

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="var(--color)" />
  </symbol>
</svg>
复制代码
<svg class="blue">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg class="red">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<style>
svg.red {
  --color: red;
}
svg.blue {
  --color: blue;
}
</style>
复制代码

查看 SVG 符号--个人 Glitch playground

验证 SVG

SVG 文件是 XML,能够用无效的格式编写,有些服务或应用程序可能不接受无效的 SVG 文件。

SVG 可使用 W3C Validator验证。

我应该包含 xmlns 属性么?

有时 SVG 别定义为

<svg>
  ...
</svg>
复制代码

有时定义为

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  ...
</svg>
复制代码

第二个表单是 XHTML。它能够与 HTML5 一块儿使用(文档具备 <!DOCTYPE html>),但在本例中,第一种形式更简单。

我应该担忧浏览器支持问题么?

在 2018 版本中,绝大多数用户的浏览器都支持 SVG。.

您仍然可使用诸如 Modernizr 这样的库来检查缺乏的支持,并提供一个后备:

if (!Modernizr.svg) {
  $(".my-svg").attr("src", "images/logo.png");
}
复制代码

掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索