渐变

除了基本的fill和stroke之外,我们还有一个更令人兴奋的功能,给边框和填充设置渐变。

渐变的类型有两种,线性渐变和径向渐变。线性渐变沿直线变化,在defs元素里创建一个 <linearGradient>元素,就创建了一个线性渐变。渐变必须有一个id属性,否则它不能被其他元素引用,等于白做了。

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

<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>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
  </defs>
 
  <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设置。上面的例子里混合使用了这两种形式。比如,这个例子的渐变是从红色开始,到中间渐变成黑色,最后渐变到蓝色。你可以按照自己的想法设置各种stop-color,但是它们的offset必须是从0%逐渐提高到100%。(如果不加%,就是0-1)。如果有重复的值,不会被分配到xml树的最后。另外像fill和stroke一样,你也可以设置一个stop-opacity属性表示透明度。(ff3里这里也可以用rgba值)

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

使用渐变时,我们需要在对象的fill或stroke属性里引用它。就像在CSS里通过url来引用其他元素一样,在这里,url引用的是我们给渐变设置的id,所以只需要将fill属性设置成url(#Gradient),我们的对象就可以呈现出五彩斑斓的效果。另外你也可以给stroke进行同样的设置。

<linearGradient>元素还可以设置其他一些属性,用来定义尺寸和样式。比如渐变的方向是由两个点控制的,它们用x1x2y1y2四个属性控制,形成一条直线,渐变就沿这条直线变化。渐变默认的方向是水平方向,使用这些属性就可以改变方向。上面例子里的Gradient2就是一个垂直的渐变。

 <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
你也可以在渐变中使用xlink:href属性,它可以将一个渐变的属性和stop节点,引入到另一个渐变中。在下面的例子里,我们就不需要在Gradient2里重新创建许多stop节点。
 <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" xlink:href="#Gradient1"/>
这里我直接在元素里定义了xlink的命名空间,通常我们会在文档的顶部定义它。在 talk about images 有更多相关内容。

径向渐变很类似线性渐变,只不过是从一个点向外发散渐变。在文档的defs段落里增加一个<radialGradient>元素,就可以创建径向渐变。

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

<svg width="120" height="240" version="1.1"
  xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="Gradient2" 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(#Gradient1)"/> 
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/> 
  
</svg>

这个例子的里,径向渐变中的stop节点在用法上和前面的线性渐变一样,但是这里的图形对象是中间呈红色,然后向各个方向发散渐变,直到边缘渐变到蓝色。径向渐变<radialGradient>也有若干用来定义位置和方向的属性,不过与线性渐变不同,这里的设置会稍微复杂一点。径向渐变里也可以设置两个点,用来确定它的范围。第一个点用来定义一个环,限定渐变的范围。该点包括坐标属性cxcy,以及半径属性r。定义这三个属性,就可以改变渐变的位置和大小,就像上面例子里的第二个渐变效果。

第二个点被称为焦点,通过坐标属性fxfy来确定。第一个点决定的是渐变所处的范围,而焦点则决定渐变的中心。看例子更好理解:

<?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"也是让渐变继续,不过是跳过返回的过程,直接回到起始状态,然后重新渐变。

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

<svg width="220" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient"
            cx="0.5" cy="0.5" r="0.25" fx=".25" fy=".25"
            spreadMethod="repeat">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
  <rect x="50" y="50" rx="15" ry="15" width="100" height="100"
       fill="url(#Gradient)"/>
</svg>

另外,两个渐变都有一个名为gradientUnits的属性,它用来决定渐变的单位。它有两个可用值:userSpaceOnUse or objectBoundingBoxobjectBoundingBox是默认值,表示渐变会使用图形对象的单位,所以你定义坐标时使用的是0到1,它们会自动计算成你的图形对象使用的尺寸。userSpaceOnUse表示要用绝对单位,所以你必须知道你的图形对象的位置,然后将渐变的位置放在那儿。于是径向渐变可以这样写:

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

你还可以使用gradientTransform属性创建其他类型的变换,但现在我们还没说道introduced transforms,所以这些内容会留到后面再讲。

当图形对象的不是方形时,还有一个需要注意的处理方式:gradientUnits="objectBoundingBox"。但是它太复杂了,需要其他大牛来讲解。

附件

檔案 Size 日期 Attached by
SVG_Linear_Gradient_Example.png
7864 位元組 2008-01-18 17:17:06 Wjjohnst
SVG_Radial_Gradient_Example.png
15216 位元組 2008-01-18 17:23:53 Wjjohnst
SVG_Radial_Grandient_Focus_Example.png
14222 位元組 2008-01-18 17:31:24 Wjjohnst
SVG_SpreadMethod_Example.png
35095 位元組 2008-01-18 17:45:51 Wjjohnst
Dimensions-offset.png
10664 位元組 2008-03-13 17:55:02 Sheppy
Di_empty.gif
14262 位元組 2006-10-01 13:47:44 Prometeo
Di_main.gif
26168 位元組 2006-10-01 13:43:18 Prometeo
Di_menu.gif
6839 位元組 2006-10-01 13:48:43 Prometeo

Document Tags and Contributors

Contributors to this page: Dx.Yang, ethertank
最近更新: ethertank,