图案

pattern(图案)是一个比较难理解的填充类型。同时,pattern的作用很强大,所以在这里需要进行一些讨论,以便对填充模式有一个大致的了解。和渐变一样,<pattern>元素也需要放在SVG文件的<ldefs>段落里。

<?xml version="1.0" standalone="no"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <linearGradient id="Gradient1">
      <stop offset="5%" stop-color="white"/>
      <stop offset="95%" stop-color="blue"/>
    </linearGradient>
    <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
      <stop offset="5%" stop-color="red"/>
      <stop offset="95%" stop-color="orange"/>
    </linearGradient>

    <pattern id="Pattern" x=".05" y=".05" width=".25" height=".25">
      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
      <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
      <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
    </pattern> 

  </defs>
  
  <rect fill="url(#Pattern)" stroke="black" x="0" y="0" width="200" height="200"/>
</svg>

在pattern元素里,你可以使用任意的基本图形元素,也可以按照之前所学的方法给它们设置样式,包括渐变和不透明度。在上面的例子里,我们在pattern元素里放了一个圆形和两个矩形元素,它们相互重叠,其中一个矩形是另一个矩形的两倍大小,用来填满pattern。

pattern最难理解的是定义尺寸和单位。在上面的例子里,我们给pattern元素定义了widthheight属性,用来描述pattern占据的尺寸范围,另外还有xy属性,用来定义pattern起点的偏移量。它们的具体解释如下:

渐变有gradientUnits属性,pattern也有一个类似的属性patternUnits,用来定义属性采用的单位,它的默认值是objectBoundingBox,等同于pattern采用的宽高缩放比是1。在上面的例子里,我们需要pattern的填充效果在纵向和横向都重复4次,所以width和height设置的值都是0.25,意思是pattern的填充效果的宽和高是整个图形宽高的1/4(0.25)。

与渐变不同的是,pattern还有另外一个属性patternContentUnits,用来描述pattern内部形状使用的单位,这个属性的默认值是userSpaceOnUse,它与patternUnits属性相反,即:如果你没定义patternContentUnits,也没有定义patternUnits,那么pattern内部采用的坐标单位,会不同于pattern采用的坐标单位。这个地方可能会有一点不好理解。在上面的例子中,我们考虑到这个图形的尺寸是200px见方,pattern需要在纵向和横向都重复4次,这意味着pattern的尺寸是50*50px的正方形,pattern内部的矩形和圆形应该位于50*50px的范围内,任何超出范围的部分都不会被显示。另外,pattern还有10px的偏移量,由于它是从左上角开始显示,所以x和y属性应该是10/200=0.05。

这里需要说明一下,当图形的尺寸发生变化时,pattern也会自动缩放,适应图形的变化,但是pattern内部的图形不会改变尺寸。所以,尽管我们仍然设置了4次重复,但pattern内部的元素仍然保持原尺寸,所以它们之间有比较大的空白。通过改变patternContentUnits属性,我们可以让所有元素使用同样的单位。

 <pattern id="Pattern" width=".25" height=".25" patternContentUnits="objectBoundingBox">
   <rect x="0" y="0" width=".25" height=".25" fill="skyblue"/>
   <rect x="0" y="0" width=".125" height=".125" fill="url(#Gradient2)"/>
   <circle cx=".125" cy=".125" r=".1" fill="url(#Gradient1)" fill-opacity="0.5"/>
 </pattern>

现在,由于pattern内部的元素和pattern本身采用相同的单位,我们就不用再设置偏移量去纠正pattern的起始位置,并且,当图形的尺寸放大时,pattern也会自动缩放,所以pattern内部的元素数目和重复次数都不会变化。这里有一个使用userSpaceOnUse的对比例子,如果图形改变尺寸,pattern会保持原尺寸,并且重复更多次,达到填满图形的效果。

在Gecko引擎中,如果圆形的半径小于 0.075将会出现一些问题。(这可能是pattern独有的bug,也可能在所有情况下都是bug,尚不确定。)为了避免这种错误出现,应尽量避免使用objectBoundingBox。

以上这些都不是我们通常理解的pattern。pattern一般会设置一个尺寸,并且独立于图形进行重复。如果像下面这样做,那么pattern和它内部的元素都会被创建在当前用户空间内,并且不会被改变:

 <pattern id="Pattern" x="10" y="10" width="50" height="50" patternUnits="userSpaceOnUse">
   <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
   <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
   <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
 </pattern>

当然,这意味着当你改变图形的尺寸后,pattern不会缩放。上面提到的三种情况都会被放在下面的例子里,将图形绘制在一个拉长到300px高度的画布上。图示可能并不详尽,你可以在你的应用里改变更多设置项。

Image:SVG_Pattern_Comparison_of_Units.pngo

文件標籤與貢獻者

 此頁面的貢獻者: ethertank, Dx.Yang
 最近更新: ethertank,