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"还有一些其他注意事项,但它们相当复杂,必须等到更有经验的人来解释。