SVG 中的漸變

除了簡單的填充和描邊之外,更令人興奮的或許是,您還可以建立和應用漸變作為填充或描邊。

SVG 漸變有兩種型別:線性漸變和徑向漸變。它們與使用它們的位置分開定義,這有助於重用。您必須為每個漸變指定一個 id 屬性,以允許其他元素引用它。漸變定義可以放在 <defs> 元素或 <svg> 元素中。

線性漸變

線性漸變沿直線變化。要插入一個線性漸變,您需要在 SVG 檔案的 <defs> 部分內建立一個 <linearGradient> 節點。

基本示例

html
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="Gradient1">
      <stop class="stop1" offset="0%" />
      <stop class="stop2" offset="50%" />
      <stop class="stop3" offset="100%" />
    </linearGradient>
    <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
      <stop offset="0%" stop-color="red" />
      <stop offset="50%" stop-color="black" stop-opacity="0" />
      <stop offset="100%" stop-color="blue" />
    </linearGradient>
  </defs>
  <style>
    #rect1 {
      fill: url("#Gradient1");
    }
    .stop1 {
      stop-color: red;
    }
    .stop2 {
      stop-color: black;
      stop-opacity: 0;
    }
    .stop3 {
      stop-color: blue;
    }
  </style>

  <rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100" />
  <rect
    x="10"
    y="120"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#Gradient2)" />
</svg>

上面是一個將線性漸變應用於 <rect> 元素的示例。線性漸變內部有多個 <stop> 節點。這些節點透過指定位置的 offset 屬性和 stop-color 屬性來告訴漸變在特定位置應該是什麼顏色。這可以直接分配,也可以透過 CSS 分配。出於本示例的目的,這兩種方法已混合使用。例如,這個例子告訴漸變從紅色開始,中間變為透明黑色,最後變為藍色。您可以插入任意數量的停止顏色,以建立您需要的漂亮或醜陋的混合,但偏移量應始終從 0%(或如果您想省略百分號,則為 0)增加到 100%(或 1)。重複的值將使用在 XML 樹中分配最遠的停止點。此外,與填充和描邊一樣,您可以指定 stop-opacity 屬性來設定該位置的不透明度(同樣,在 FF3 中,您也可以使用 rgba 值來完成此操作)。

svg
<stop offset="100%" stop-color="yellow" stop-opacity="0.5"/>

要使用漸變,您必須從物件的 fillstroke 屬性中引用它。這與您在 CSS 中引用元素的方式相同,使用 url。在這種情況下,url 只是對我們漸變的引用,該漸變具有創意 ID“Gradient1”。要附加它,將 fill 設定為 url("#Gradient1"),瞧!我們的物件現在是多色的。您可以對 stroke 執行相同的操作。

svg
<style>
  #rect1 {
    fill: url("#Gradient1");
  }
</style>

<linearGradient> 元素還接受其他幾個屬性,這些屬性指定漸變的大小和外觀。漸變的方向由兩個點控制,由屬性 x1x2y1y2 指定。這些屬性定義了漸變所沿的線。漸變預設為水平方向,但可以透過更改這些屬性來旋轉它。上面示例中的 Gradient2 旨在建立垂直漸變。

html
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"></linearGradient>

注意:您也可以在漸變上使用 href 屬性。使用此屬性時,一個漸變的屬性和停止點可以包含在另一個漸變中。在上面的示例中,您不必在 Gradient2 中重新建立所有停止點。

html
<linearGradient id="Gradient1">
  <stop id="stop1" offset="0%" />
  <stop id="stop2" offset="50%" />
  <stop id="stop3" offset="100%" />
</linearGradient>
<linearGradient
  id="Gradient2"
  x1="0"
  x2="0"
  y1="0"
  y2="1"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  href="#Gradient1" />

我們在這裡直接在節點上包含了 xlink 名稱空間,儘管通常您會在文件頂部定義它。當我們談論影像時,會對此有更多介紹。

徑向漸變

徑向漸變與線性漸變相似,但它們繪製的漸變從一個點向外輻射。要建立徑向漸變,您需要在文件的 <defs> 部分新增一個 <radialGradient> 元素。

基本示例

html
<?xml version="1.0" standalone="no"?>
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <radialGradient id="RadialGradient1">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
    <radialGradient id="RadialGradient2" cx="0.25" cy="0.25" r="0.25">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
  </defs>

  <rect
    x="10"
    y="10"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#RadialGradient1)" />
  <rect
    x="10"
    y="120"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#RadialGradient2)" />
</svg>

這裡使用的停止點與之前相同,但現在物件中心將是紅色,並向各個方向逐漸變為藍色。與線性漸變一樣,<radialGradient> 節點可以接受多個屬性來描述其位置和方向。然而,與線性漸變不同,它要複雜得多。徑向漸變再次由兩個點定義,這兩個點決定了它的邊緣。第一個點定義了一個漸變結束的圓。它需要一箇中心點,由 cxcy 屬性指定,以及一個半徑 r。設定這三個屬性將允許您移動漸變並更改其大小,如上面第二個 rect 所示。

第二個點稱為焦點,由 fxfy 屬性定義。第一個點描述了漸變的邊緣,而焦點描述了它的中間位置。透過示例更容易理解這一點。

中心點和焦點

html
<?xml version="1.0" standalone="no"?>

<svg width="120" height="120" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
  </defs>

  <rect
    x="10"
    y="10"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#Gradient)"
    stroke="black"
    stroke-width="2" />

  <circle
    cx="60"
    cy="60"
    r="50"
    fill="transparent"
    stroke="white"
    stroke-width="2" />
  <circle cx="35" cy="35" r="2" fill="white" stroke="white" />
  <circle cx="60" cy="60" r="2" fill="white" stroke="white" />
  <text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">
    (fx,fy)
  </text>
  <text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">
    (cx,cy)
  </text>
</svg>

如果焦點移到前面描述的圓圈之外,漸變將無法正確渲染,因此該點將被假定為在圓圈邊緣之內。如果沒有給出焦點,則假定它與中心點在同一位置。

線性和徑向漸變還接受其他幾個屬性來描述它們可能經歷的變換。我在這裡想提及的唯一其他屬性是 spreadMethod 屬性。此屬性控制當漸變到達其終點但物件尚未填充時會發生什麼。它可以採用三個值之一:"pad""reflect""repeat""pad" 是您到目前為止所看到的。當漸變到達其終點時,最終偏移顏色用於填充物件的其餘部分。"reflect" 導致漸變繼續,但反向反射,從 100% 處的顏色偏移開始,然後返回到 0% 處的偏移,然後再返回。"repeat" 也允許漸變繼續,但不是向後,而是直接跳回開頭並再次執行。

擴充套件方法

html
<?xml version="1.0" standalone="no"?>

<svg width="220" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <radialGradient
      id="GradientPad"
      cx="0.5"
      cy="0.5"
      r="0.4"
      fx="0.75"
      fy="0.75"
      spreadMethod="pad">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
    <radialGradient
      id="GradientRepeat"
      cx="0.5"
      cy="0.5"
      r="0.4"
      fx="0.75"
      fy="0.75"
      spreadMethod="repeat">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
    <radialGradient
      id="GradientReflect"
      cx="0.5"
      cy="0.5"
      r="0.4"
      fx="0.75"
      fy="0.75"
      spreadMethod="reflect">
      <stop offset="0%" stop-color="red" />
      <stop offset="100%" stop-color="blue" />
    </radialGradient>
  </defs>

  <rect
    x="10"
    y="10"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#GradientPad)" />
  <rect
    x="10"
    y="120"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#GradientRepeat)" />
  <rect
    x="120"
    y="120"
    rx="15"
    ry="15"
    width="100"
    height="100"
    fill="url(#GradientReflect)" />

  <text x="15" y="30" fill="white" font-family="sans-serif" font-size="12pt">
    Pad
  </text>
  <text x="15" y="140" fill="white" font-family="sans-serif" font-size="12pt">
    Repeat
  </text>
  <text x="125" y="140" fill="white" font-family="sans-serif" font-size="12pt">
    Reflect
  </text>
</svg>

兩種漸變還有一個名為 gradientUnits 的屬性,它描述了您在描述漸變大小或方向時將使用的單位系統。這裡有兩種可能的值:"userSpaceOnUse""objectBoundingBox""objectBoundingBox" 是預設值,所以這就是到目前為止所展示的。它實質上將漸變縮放到物件的大小,因此您只需指定從零到一的值的座標,它們就會自動縮放到物件的大小。userSpaceOnUse 本質上接受絕對單位。所以您必須知道物件的位置,並將漸變放置在相同的位置。上面的徑向漸變將被重寫

html
<radialGradient
  id="Gradient"
  cx="60"
  cy="60"
  r="50"
  fx="35"
  fy="35"
  gradientUnits="userSpaceOnUse"></radialGradient>

您還可以透過使用 gradientTransform 屬性將另一個變換應用於漸變,但由於我們尚未介紹變換,我們將把它留到以後再討論。

當物件邊界框不是正方形時,處理 gradientUnits="objectBoundingBox" 還有一些其他注意事項,但它們相當複雜,需要更瞭解情況的人來解釋。