aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/svg/tutorial/patterns/index.html
blob: a4a8723e39efde2530b4599ca50c03064cff50e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
---
title: 图案
slug: Web/SVG/Tutorial/Patterns
translation_of: Web/SVG/Tutorial/Patterns
---
<p>{{ PreviousNext("SVG/Tutorial/Gradients", "SVG/Tutorial/Texts") }}</p>
<p>pattern(图案)是一个比较难理解的填充类型。同时,pattern的作用很强大,所以在这里需要进行一些讨论,以便对填充模式有一个大致的了解。和渐变一样,<a href="/en/SVG/Element/pattern" title="en/SVG/Element/pattern"><code>&lt;pattern&gt;</code></a>元素也需要放在SVG文件的<code>&amp;ltldefs&gt;</code>段落里。</p>
<p><img align="right" alt="" class="internal" src="/@api/deki/files/350/=SVG_Pattern_Example.png"></p>
<pre>&lt;?xml version="1.0" standalone="no"?&gt;
&lt;svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1"&gt;
  &lt;defs&gt;
    &lt;linearGradient id="Gradient1"&gt;
      &lt;stop offset="5%" stop-color="white"/&gt;
      &lt;stop offset="95%" stop-color="blue"/&gt;
    &lt;/linearGradient&gt;
    &lt;linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"&gt;
      &lt;stop offset="5%" stop-color="red"/&gt;
      &lt;stop offset="95%" stop-color="orange"/&gt;
    &lt;/linearGradient&gt;

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

  &lt;/defs&gt;

  &lt;rect fill="url(#Pattern)" stroke="black" x="0" y="0" width="200" height="200"/&gt;
&lt;/svg&gt;</pre>
<p>在pattern元素里,你可以使用任意的基本图形元素,也可以按照之前所学的方法给它们设置样式,包括渐变和不透明度。在上面的例子里,我们在pattern元素里放了一个圆形和两个矩形元素,它们相互重叠,其中一个矩形是另一个矩形的两倍大小,用来填满pattern。</p>
<p>pattern最难理解的是定义尺寸和单位。在上面的例子里,我们给pattern元素定义了<code>width</code><code>height</code>属性,用来描述pattern占据的尺寸范围,另外还有<code>x</code><code>y</code>属性,用来定义pattern起点的偏移量。它们的具体解释如下:</p>
<p>渐变有<code>gradientUnits</code>属性,pattern也有一个类似的属性<code>patternUnits</code>,用来定义属性采用的单位,它的默认值是objectBoundingBox,等同于pattern采用的宽高缩放比是1。在上面的例子里,我们需要pattern的填充效果在纵向和横向都重复4次,所以width和height设置的值都是0.25,意思是pattern的填充效果的宽和高是整个图形宽高的1/4(0.25)。</p>
<p>与渐变不同的是,pattern还有另外一个属性<code>patternContentUnits</code>,用来描述pattern内部形状使用的单位,这个属性的默认值是userSpaceOnUse,它与patternUnits属性相反,即:如果你没定义patternContentUnits,也没有定义patternUnits,那么pattern内部采用的坐标单位,会不同于pattern采用的坐标单位。这个地方可能会有一点不好理解。在上面的例子中,我们考虑到这个图形的尺寸是200px见方,pattern需要在纵向和横向都重复4次,这意味着pattern的尺寸是50*50px的正方形,pattern内部的矩形和圆形应该位于50*50px的范围内,任何超出范围的部分都不会被显示。另外,pattern还有10px的偏移量,由于它是从左上角开始显示,所以x和y属性应该是10/200=0.05。</p>
<p>这里需要说明一下,当图形的尺寸发生变化时,pattern也会自动缩放,适应图形的变化,但是pattern内部的图形不会改变尺寸。所以,尽管我们仍然设置了4次重复,但pattern内部的元素仍然保持原尺寸,所以它们之间有比较大的空白。通过改变<code>patternContentUnits</code>属性,我们可以让所有元素使用同样的单位。</p>
<pre class="eval"> &lt;pattern id="Pattern" width=".25" height=".25" patternContentUnits="objectBoundingBox"&gt;
   &lt;rect x="0" y="0" width=".25" height=".25" fill="skyblue"/&gt;
   &lt;rect x="0" y="0" width=".125" height=".125" fill="url(#Gradient2)"/&gt;
   &lt;circle cx=".125" cy=".125" r=".1" fill="url(#Gradient1)" fill-opacity="0.5"/&gt;
 &lt;/pattern&gt;
</pre>
<p>现在,由于pattern内部的元素和pattern本身采用相同的单位,我们就不用再设置偏移量去纠正pattern的起始位置,并且,当图形的尺寸放大时,pattern也会自动缩放,所以pattern内部的元素数目和重复次数都不会变化。这里有一个使用userSpaceOnUse的对比例子,如果图形改变尺寸,pattern会保持原尺寸,并且重复更多次,达到填满图形的效果。</p>
<p>在Gecko引擎中,如果圆形的半径小于 0.075将会出现一些问题。(这可能是pattern独有的bug,也可能在所有情况下都是bug,尚不确定。)为了避免这种错误出现,应尽量避免使用objectBoundingBox。</p>
<p>以上这些都不是我们通常理解的pattern。pattern一般会设置一个尺寸,并且独立于图形进行重复。如果像下面这样做,那么pattern和它内部的元素都会被创建在当前用户空间内,并且不会被改变:</p>
<pre class="eval"> &lt;pattern id="Pattern" x="10" y="10" width="50" height="50" patternUnits="userSpaceOnUse"&gt;
   &lt;rect x="0" y="0" width="50" height="50" fill="skyblue"/&gt;
   &lt;rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/&gt;
   &lt;circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/&gt;
 &lt;/pattern&gt;
</pre>
<p>当然,这意味着当你改变图形的尺寸后,pattern不会缩放。上面提到的三种情况都会被放在下面的例子里,将图形绘制在一个拉长到300px高度的画布上。图示可能并不详尽,你可以在你的应用里改变更多设置项。</p>
<p><img alt="Image:SVG_Pattern_Comparison_of_Units.png" class="internal" src="/@api/deki/files/349/=SVG_Pattern_Comparison_of_Units.png">o</p>
<p>{{ PreviousNext("SVG/Tutorial/Gradients", "SVG/Tutorial/Texts") }}</p>
<p>{{ languages( { "ja": "ja/SVG/Tutorial/Patterns"} ) }}</p>