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 名稱空間,儘管通常您會在文件頂部定義它。當我們討論影像時,將詳細介紹這一點。

徑向漸變

徑向漸變類似於線性漸變,但繪製從一個點輻射出來的漸變。要建立一個徑向漸變,您可以將一個<radialGradient>元素新增到文件的<defs>部分。

基本示例

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"也允許漸變繼續,但它不是向後移動,而是直接跳回開頭並再次執行。

spreadMethod

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"還有一些其他注意事項,但它們相當複雜,必須等到更有經驗的人來解釋。