一个并非全部是…SVG 的 SVG

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

当你想到 SVG 时,你会想到什么?矢量图形,对吧?SVG 绝对是一种矢量图形格式。但它不仅仅是这些。你可以在其中设置字体。你可以在其中放置光栅图形。它具有交互性和动画性。它更像是一种多媒体图形格式。

也许你一开始会想到这样的东西

这很好。SVG 绝对擅长处理这样的图形。其质量和文件大小无与伦比。

但是 SVG 不仅仅是绘制图形的语法。它远不止于此。让我们看看 SVG 还可以做的一些事情,这对你们中的一些人来说可能有点令人大开眼界。

  • 您可以在 SVG 中设置字体;
  • 您可以在 SVG 中设置光栅图形;
  • 并且您可以在 SVG 中进行交互和动画。

让我们将所有这些都整合到一个 SVG 中,以便您了解它们是如何工作的。并且我会在此过程中添加一些奖励。

由于博客平台的限制,此博文中使用的图形将是 .png 文件。不过,这并非浏览器限制。这里介绍的所有内容在所有浏览器中都得到了很好的支持。如果您想查看实际的 SVG,请在此处查看

1) 从矢量图形开始

可以这么说,这是我们的舞台

<svg viewBox="0 0 300 180">
</svg>

在其中,我可以绘制矢量内容。例如 <circle><polygon> 或任何其他 SVG 绘制内容。

<svg viewBox="0 0 300 180">
 <polygon points=" … ">

 <circle … />
 <circle … />
 <circle … />
</svg>

以下是我们 SVG 舞台上一些相当简单的矢量图形的示例

2) 添加光栅图形

在 HTML 中,我们有 <img> 元素。在 SVG 中并没有太大区别!就像这样

<svg viewBox="0 0 300 180">
 …

 <image xlink:href="/images/wonder-woman.jpg"  width="945" height="370" />
</svg>

这会将该图像直接放置到 SVG 中。请注意 width 和 height 属性以控制其大小。我们还可以使用 x 和 y 属性来控制位置,或者使用 transform 属性来微调和调整大小。

3) 使用矢量剪裁光栅

让我们将矢量和光栅结合起来一段时间。我们别无选择,只能将我们的光栅图形制作成矩形。我们可以使用 alpha 透明度来模拟其他形状,但我们可以比这更高效。

假设我们要将该光栅图形剪裁成一个圆形。使用 SVG 中的 <clipPath> 没有任何问题。让我们定义一个

<svg viewBox="0 0 300 180">

 <defs>
   <clipPath id="circle">
     <circle cx="150" cy="65" r="50" />
   </clipPath>
 </defs>

 …
</svg>

<circle> 不会自行绘制 - 在这种情况下,它只是圆形的定义,定义了剪裁路径。将其应用于某些其他元素,并且将在该区域内显示任何内容(其余内容将被隐藏)。

如果将其应用于我们的图像(将其应用于包装元素很有帮助,因此我们可以独立于剪裁来调整内容),我们就会得到我们想要的结果

4) 在 SVG 中设置字体

由于 SVG 中的图像元素略有不同,因此文本元素也略有不同。

在 HTML 中,我们有很多:<h2><p><li><dd>,等等。在 SVG 中基本上只有一个:<text>

您可以使用 x 和 y 坐标设置要放置的位置,以及 font-familyfont-size 等预期属性。在我们的示例中,我们将通过将其定位在 x="50%" 处并使用 text-anchor="middle" 来居中显示字体。

<svg viewBox="0 0 300 180">
 …

 <text x="50%" y="140" text-anchor="middle" font-size="26" font-family="'flood-std', sans-serif" fill="white">
   Wonder Woman
 </text>

 …
</svg>

看到那里的“flood-std”字体系列了吗?不是正常的网络安全字体,对吧?请记住,这就像我们在 HTML 中使用的普通网络字体一样。我们可以使用网络字体!我正在通过 Typekit 加载字体 Flood,只是为了证明这一点。

我将添加更多字体,也居中,但大小、颜色和字母间距不同

5) 渐变

这是一个小小的奖励:SVG 可以定义渐变。例如,这个简单的透明 -> 白色 -> 透明渐变

<svg viewBox="0 0 300 180">

 <defs>
   …

   <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
     <stop offset="0%" stop-color="white" stop-opacity="0" />
     <stop offset="50%" stop-color="white" stop-opacity="0.33" />
     <stop offset="100%" stop-color="white" stop-opacity="0" />
   </linearGradient>
 </defs>

</svg>

我们将使用它来填充文本之间的线条,只是为了好玩

6) 光线动画

到目前为止,我们所做的一些事情我们可以在 CSS 中完成。例如,我们可以像这样在 CSS 中设置文本的字体系列

text {
 font-family: ‘flood-std’, sans-serif;
}

如果有很多文本元素,这将比将其设置为每个文本元素的属性更有效。但是,这里的教训是 CSS 也适用于 SVG。很酷,对吧?包括像动画这样的东西。

我们如何处理那些环以实现悬停效果呢?

svg:hover > circle {
 transition: 0.3s transform, 0.2s stroke;
 transform-origin: center center;
 stroke: red;
}
svg:hover > circle:nth-of-type(2) {
 transform: scale(0.89);
}
svg:hover > circle:nth-of-type(3) {
 transform: scale(0.75);
}

没错

当然,CSS 并不是动画 SVG 的唯一方法 - 有三种方法。如果您正在做任何稍微复杂的事情,那么您不会后悔查看 Greensock

为什么?缩放。

哦,对了。我们为什么要在 SVG 而不是 HTML 中这样做?好吧,请记住其中的所有矢量。SVG 在以一种既能产生高品质又能产生低文件大小的方式绘制这些内容方面非常高效。

我们决定在其中使用光栅图形,而光栅就是光栅,因此无论我们在哪里使用它,它都大致相同。

您可能会争辩说,我们在 SVG 中对字体的控制较少,语义也较少。在某种意义上是正确的,在其他方面则不是。我们在 SVG 中有一些非常酷的字体控制可能性,例如在路径上设置字体。

但最重要的是什么?可扩展性!SVG 舞台上的所有内容都根据我们的纵横比很好地缩放。

最终演示

查看 Chris Coyier 编写的 Pen
SVG 是一种跨媒体格式!
@chriscoyier
CodePen 上。

未来内容

SVG 2 是什么以及是否会实现尚不清楚。但是 有一个规范定义了更多 HTML 内容可以嵌入到 SVG 中。即:视频、音频、iframe 和 canvas。通过这个例子,我认为我们可以理解为什么这很酷。SVG 确实是一种跨媒体格式!