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 命名空间,尽管通常您会在文档顶部定义它。当我们讨论图像时,将详细介绍这一点。
径向渐变
径向渐变类似于线性渐变,但绘制从一个点辐射出来的渐变。要创建一个径向渐变,您可以将一个<radialGradient>
元素添加到文档的<defs>
部分。
基本示例
<?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"
也允许渐变继续,但它不是向后移动,而是直接跳回开头并再次运行。
spreadMethod
<?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"
还有一些其他注意事项,但它们相当复杂,必须等到更有经验的人来解释。