模式

模式

模式可以說是 SVG 中比較令人困惑的填充型別之一。它們功能強大,因此值得討論並至少掌握其基本概念。與漸變一樣,<pattern> 元素應放在 SVG 檔案的 <defs> 部分。

html
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <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="0" y="0" 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" width="200" height="200" />
</svg>

<pattern> 元素內部,您可以包含之前包含的任何其他基本形狀,並且可以使用之前學習的任何樣式對其進行樣式設定,包括漸變和不透明度。在這裡,我們只是在圖案內部繪製了兩個矩形元素(它們重疊,其中一個的大小是另一個的兩倍,用於填充整個圖案)和一個圓形。

關於模式令人困惑的一點是定義單位系統及其大小。在上面的示例中,我們在模式元素上定義了 widthheight 屬性來描述模式在開始重複自身之前應該延伸多遠。如果您想將此矩形的起始點偏移到繪圖中的某個位置,還可以使用 xy 屬性。此處使用它們的原因在下面進行了描述。

與上面使用的 gradientUnits 屬性一樣,模式也具有一個屬性 patternUnits,它指定這些屬性將採用的單位。它預設為 "objectBoundingBox",如上所述,因此值為 1 將縮放為應用模式的物件的 widthheight。由於在這種情況下,我們希望模式水平和垂直重複 4 次,因此 heightwidth 設定為 0.25。這意味著模式的 widthheight 僅佔總框大小的 0.25

與漸變不同,模式具有第二個屬性 patternContentUnits,它描述了模式元素內部、基本形狀本身使用的單位系統。此屬性預設為 "userSpaceOnUse",與 patternUnits 屬性相反。這意味著,除非您指定這兩個屬性之一或兩者(patternContentUnitspatternUnits),否則您在模式內繪製的形狀將在與模式元素使用的不同的座標系中繪製,這在您手動編寫時可能會造成一些混亂。

為了使這在上面的示例中起作用,我們必須考慮框的大小(200 畫素)以及我們希望模式水平和垂直重複 4 次這一事實。這意味著每個模式單位都是一個 50×50 的正方形。然後將模式內的兩個矩形和圓形調整大小以適合 50×50 的框中。我們在該框之外繪製的任何內容都不會顯示。模式還必須偏移 10 畫素,以便從框的左上角開始,因此必須將 patternxy 屬性調整為 10÷200 = 0.05。

這裡的警告是,如果物件的大小發生變化,模式本身將縮放以適應它,但內部的物件不會。因此,雖然我們仍然在模式內部有 4 個重複單元,但構成該模式的物件將保持相同的大小,並且最終會在它們之間出現大片空白區域。透過更改 patternContentUnits 屬性,我們可以將所有元素放入相同的單位系統中。

xml
 <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>

現在,由於模式內容與模式位於相同的單位系統中,因此我們不必偏移框以使模式從正確的位置開始,並且如果物件的大小更改為更大的大小,模式將自動縮放,以便在其中具有相同數量的物件和重複次數。這與 "userSpaceOnUse" 系統形成對比,在該系統中,如果物件更改大小,模式將保持不變,並且只需重複更多次以填充框。

順便說一句,在 Gecko 中,如果圓形的半徑設定為小於 0.075 的值,則似乎會出現繪圖問題(目前尚不清楚這是模式元素中的錯誤還是其他問題)。為了解決這個問題,最好避免在 "objectBoundingBox" 單位中進行繪製,除非您必須這樣做。

以上兩種用法都不是您想到模式時通常會想到的。模式通常具有固定的大小並獨立於物件形狀重複自身。要建立類似這樣的內容,模式及其內容都必須在當前的 userSpace 中繪製,因此如果物件發生變化,它們不會改變形狀。

xml
 <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>

當然,這意味著如果您稍後更改物件大小,模式將不會縮放。以下三個示例顯示在矩形上,該矩形已略微拉長,高度為 300px,但我應該注意,這不是詳盡的圖片,根據您的應用,還有其他選項可用。

Three examples showing patternUnits values of default and userSpaceOnUse and patternContentUnits values of default and objectBoundingBox. When both are set to default, the aspect ratio is maintained with white space visible. Setting patternContentUnits to objectBoundingBox effects the aspect ratio to remove white space. Setting patternUnits to userSpaceOnUse maintains the aspect ratio while eliminating white space.