SVG 中的渐变
除了简单的填充和描边之外,更令人兴奋的或许是,您还可以创建和应用渐变作为填充或描边。
SVG 渐变有两种类型:线性渐变和径向渐变。它们与使用它们的位置分开定义,这有助于重用。您必须为每个渐变指定一个 id
属性,以允许其他元素引用它。渐变定义可以放在 <defs>
元素或 <svg>
元素中。
线性渐变
线性渐变沿直线变化。要插入一个线性渐变,您需要在 SVG 文件的 <defs>
部分内创建一个 <linearGradient>
节点。
基本示例
<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 值来完成此操作)。
<stop offset="100%" stop-color="yellow" stop-opacity="0.5"/>
要使用渐变,您必须从对象的 fill
或 stroke
属性中引用它。这与您在 CSS 中引用元素的方式相同,使用 url
。在这种情况下,url 只是对我们渐变的引用,该渐变具有创意 ID“Gradient1”。要附加它,将 fill
设置为 url("#Gradient1")
,瞧!我们的对象现在是多色的。您可以对 stroke
执行相同的操作。
<style>
#rect1 {
fill: url("#Gradient1");
}
</style>
<linearGradient>
元素还接受其他几个属性,这些属性指定渐变的大小和外观。渐变的方向由两个点控制,由属性 x1
、x2
、y1
和 y2
指定。这些属性定义了渐变所沿的线。渐变默认为水平方向,但可以通过更改这些属性来旋转它。上面示例中的 Gradient2 旨在创建垂直渐变。
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"></linearGradient>
注意:您也可以在渐变上使用 href
属性。使用此属性时,一个渐变的属性和停止点可以包含在另一个渐变中。在上面的示例中,您不必在 Gradient2 中重新创建所有停止点。
<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>
元素。
基本示例
<?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>
节点可以接受多个属性来描述其位置和方向。然而,与线性渐变不同,它要复杂得多。径向渐变再次由两个点定义,这两个点决定了它的边缘。第一个点定义了一个渐变结束的圆。它需要一个中心点,由 cx
和 cy
属性指定,以及一个半径 r
。设置这三个属性将允许您移动渐变并更改其大小,如上面第二个 rect
所示。
第二个点称为焦点,由 fx
和 fy
属性定义。第一个点描述了渐变的边缘,而焦点描述了它的中间位置。通过示例更容易理解这一点。
中心点和焦点
<?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="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
本质上接受绝对单位。所以您必须知道对象的位置,并将渐变放置在相同的位置。上面的径向渐变将被重写
<radialGradient
id="Gradient"
cx="60"
cy="60"
r="50"
fx="35"
fy="35"
gradientUnits="userSpaceOnUse"></radialGradient>
您还可以通过使用 gradientTransform
属性将另一个变换应用于渐变,但由于我们尚未介绍变换,我们将把它留到以后再讨论。
当对象边界框不是正方形时,处理 gradientUnits="objectBoundingBox"
还有一些其他注意事项,但它们相当复杂,需要更了解情况的人来解释。