如何使用SVG图案

发布于 彦子

图案是非常常用的设计元素。它可以提供对比,创建一个深度感,并给组合添加趣味。SVG可以很方便地创建和使用图案,随心所欲~

我上次提到了这周要讨论一个可以定义并重用的元素,就是pattern啦。

这篇文章我们要讨论<pattern>元素,以及如何在SVG中使用这个元素。大概会讲SVG图案的基础,然后下一篇讲解如何创建复杂一些的图案。

SVG图案

SVG图案一般用于SVG图形对象的填充fill或描边stroke。这个图形可以是一个SVG元素,也可以是位图图像,通过<pattern>元素在x轴或y轴方向以固定的间隔平铺。

你可以在<pattern>元素内定义图案,然后通过id引用。下面我们结合实例来讲解。

一个简单的图案示例

我们从一个简单的实例开始,这里我创建了一个重复的圆的图案。同样,如果你阅读了前面几篇关于SVG的文章,这些代码看起来都是很相似的。

<svg width="660" height="220">
 <defs>
   <pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
     <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />
   </pattern>
 </defs>

 <rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern)" />
</svg>

<defs>标签内定义图案。<pattern>元素中的内容直到引用的时候才会显示。<pattern>中定义一个id,方便在后面被矩形引用。<rect>元素使用图案作为填充,然后再使用纯色来作为描边。

<pattern>元素内,我们定义了一个半径为10(px)的绿色圆。cxcy的值(分别为10px)设置了circle元素的初始圆的原点,或它的左上角。

这听起来可能有点奇怪。圆怎么可能有一个左上角或者任何的角呢?不过记住我们是通过一个矩形的视窗来看SVG图形的,所以矩形区域内展示的圆确实是有一个左上角的。

在讨论剩下的代码之前,我们先来看看当前的图形长啥样。基本是一个重复绿色圆的图案。

现在来看看<pattern>元素的属性。

<pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">

xy属性定义了图案的起点。这里我把它们都设置为0,这样在图案开始前就不会有偏移了。前面circle已经设置了中心在原点。设置xy0,使得圆形的中心和图案的起点对齐了。

widthheight属性定义了重复图案的宽度和高度。这里我给它们设置了相同的尺寸,为圆的直径,所以图案是一个一个圆挨着重复的。

理解<pattern>元素的属性

我们来依次改变这些属性的值,看看每个属性都对应什么效果。这是当xy的值都变成10之后,输出的SVG。

<pattern id=“pattern" x=“10" y=“10" width=“20" height=“20" patternUnits="userSpaceOnUse">

第一眼看起来好像是没什么区别,但是仔细看看左上角的第一个圆。我们注意到它从绿色小圆的边缘开始重复的,而不是中心。也就是说,改变<pattern>元素的xy的值,会改变整个图案的位置。

我们把xy的值设置回0,这次我们来调整patternwidthheight值。这是当widthheight都被设置为25时的效果,初始示例中设置的是20

<pattern id=“pattern" x=“0" y=“0" width=“25" height=“25" patternUnits="userSpaceOnUse">

得到的图案和第一个实例的起点位置一样,是左上角的圆的中心。注意到在各个圆之间有一些空间。这是因为本来每个圆的宽度是20px,但是图案设置了是25px重复一次图案,所以各个圆之间就留下了5px空白

也就是说pattern的widthheight决定的是下一个pattern出现的位置,它们允许你在pattern之间加入额外的空白。

最后一个属性是patternUnits,定义pattern的坐标系统。它的可能值有两个,userSpaceOnUseobjectBoundingBox

  • userSpaceOnUse:xywidthheight表示的值都是当前用户坐标系统的值。也就是说,这些值没有缩放,都是绝对值。
  • objectBoundingBox(默认值):xywidthheight表示的值都是外框的坐标系统(包裹pattern的元素)。也就是说,图案的单位进行了一个缩放,比如:pattern中为1的值,会变成和包裹元素的外框的widthheight一样的大小。

如果上面的定义还是理解不了,不要担心。只需要记住userSpaceOnUse不会对pattern的单位进行缩放,但是objectBoundingBox会。

这系列文章的前面我们已经讨论过了重用SVG元素,所以这里重点是看看要缩放的元素。大多数情况应该是使用userSpaceOnUse。不过,这还是取决于你的项目的具体情况。

在这篇文章中目前为止的例子中,我用的都是userSpaceOnUse。这里有一个patternUnits设置为objectBoundingBox的实例。

<pattern id="pattern" x=“0" y="0" width=“20" height="20" patternUnits="objectBoundingBox">

图案发生了什么?因为我们把patternUnits的值改成了objectBoundingBox,而widthheight都是20,会被放大,至于它们具体是按照600px(矩形的宽度)还是200px(矩形的高度)放大,需要根据方向是x还是y来确定(水平方向是x600,垂直方向是x200)。圆形图案下一次出现的位置是在矩形之外。

使用objectBoundingBox这个值时,widthheight必须小于1.0,不然图案就只会出现一次。

<svg width="660" height="220">
 <defs>
   <pattern id="pattern" x="0" y="0" width="0.0333" height="0.1" patternUnits="objectBoundingBox">
     <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />
   </pattern>
 </defs>

 <rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern)" />  
</svg>

结果如下。

你可能会很好奇我怎么得出xy0.03330.1的。因为:

20 (circle height) ÷ 200 (rectangle height) = 0.1
20 (circle width) ÷ 600 (rectangle width) = 0.0333

不过还是userSpaceOnUse更易于使用,而且大多数时候我们都是希望图案保留绝对值尺寸,但有时你可能想要pattern缩放,这个时候可能objectBoundingBox更好用。

使用pattern描边

我前面提到你可以使用图案作为填充和描边,尽管我这里只写了图案作为填充的示例。你可以尝试把它作为描边,看看其工作效果。

<svg width="660" height="220">
 <defs>
   <pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
     <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />
   </pattern>
 </defs>

 <rect x="10" y="10" width="600" height="200" stroke="url(#pattern)" stroke-width="20px" fill="#630" />
</svg>

还是那个我们已经用了很多次的图案实例。这是我最初使用的那个示例的副本,只对矩形做了一点改变。

早前我给矩形的填充引用了pattern。这里我把它作为描边,然后使用纯色来作填充。我把stroke-width设置为20px,这样圆圈才能完整显示出来。

结果如下。

pattern现在填充的是描边,而不是元素的背景。有一点需要注意的是,我们移动图案的位置只是在border之内移动。而不会移动整个border

例如,这是SVG标签的内容,当我把xy设置为10。图案就向右边和下边各移动了10px

<pattern id="pattern" x=“10" y=“10" width=“20" height=“20" patternUnits="userSpaceOnUse">

多尝试,还是可以创建出很有趣的图案的。

我们今天先讲到这里,图案这部分内容还没有讲完。我们下次再见。

总结

图案可以给组合元素添加很多有趣的东西,SVG创建图案也非常容易。使用简单的图形和线条就可以定义很有趣的图案,然后通过fillstroke属性就可以把它们赋给SVG对象。

今天讲得主要是图案的基础内容,还有很多。下次我们再继续讲讲一些可以给<pattern>元素添加的属性。然后我会给你展示如何在图案中嵌套图案,来创建更复杂的图案。

本文根据@Steven Bradley的《How To Work With SVG Patterns》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://vanseodesign.com/web-design/svg-pattern-element/

彦子

在校学生,本科计算机专业。逗比一枚,热爱前端热爱生活,喜欢CSS喜欢JavaScript喜欢SVG,爱玩PS玩AI玩啊逗比的软件。努力向上,厚积薄发。

如需转载,烦请注明出处:https://www.fedev.cn/svg/svg-pattern-element.htmlClimacool Vent M