posts - 40, comments - 13, trackbacks - 0, articles - 1
  IT博客 :: 首页 :: 新随笔 :: 联系 ::  :: 管理

在SVG中使用滤镜效果和输出文字


孟宪会
01-12-18 下午 02:14:13


为了使图像更生动形象,可以在SVG中使用滤镜效果和输出文字的基本方法。
一、在SVG中使用滤镜效果
在SVG中,我们可以直接对基本图象和文字使用这些效果,在SVG使用滤竟效果就和Adobe Photoshop、Macromedia Fireworks中一样,比如:阴影、高斯模糊、金属效果,颜色渐变等,SVG中的滤镜效果有feBlend、feColorMatrix、feComponentTransfer、feComposite、feConvolveMatrix、feDiffuseLighting、feDisplacementMap、feFlood、feGaussianBlur、feImage、feMerge、feMorphology、feOffset、feSpecularLighting、feTile、feTurbalance、feDistantLight、fePointLight、feSpotLight等。我们可以单独使用这些滤镜效果,也可以组合起来使用。由于这些滤镜的组合很多,我们很难在较短的篇幅里全部讲述,我们只是举其中的几个例子,来让初步认识一下在SVG中如何使用滤镜。
要在SVG中使用滤镜效果,必须把滤镜的定义嵌套在<defs>标记中,顾名思义,defs就是定义(definitions)的意思,它的作用就是定义一些特殊的元素,滤镜的定义也必须放到其中。定义一个滤镜效果,必须使用<filter>标记,同时必须指定一个id名(即唯一标识符),用以标识这个效果是应用到哪些图像上,下面举个具体的例子来加以说明:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400" height="400">
<defs>
<filter id="Gaussian_Blur_Test_for_Mengxianhui">
<feGaussianBlur in="SourceGraphic" stdDeviation="2"/>
</filter>
</defs>
<rect x="59" y="77" width="163" height="34" style="filter:url(#Gaussian_Blur_Test_for_Mengxianhui);fill:rgb(128,128,255);stroke:rgb(128,0,128);stroke-width:5;" />
</svg>
在上面的例子中,<filter id="Gaussian_Blur_Test_for_Mengxianhui">标记定义了一个高斯模糊的滤镜效果,id值在整个文件中应当是唯一的,文档中的其它元素也可以通过这个id值来重复使用这个滤镜,换句话说,<filter id="Gaussian_Blur_Test_for_Mengxianhui">就相当于一个模板,可以多次被调用。当我们要对某元素使用这个滤镜时,采用的语法是:filter:url(#Gaussian_Blur_Test_for_Mengxianhui),并把它做为style属性的一部分,圆括号的“#”不能省略,它后面的文字就是滤镜定义中的id值。滤镜效果的定义放到<feGaussianBlur in="SourceGraphic" stdDeviation="2"/>标记中,前导符“fe”在所有的滤镜中都有,是filter effect的缩写。例子中的滤镜效果是高斯模糊,stdDeviation属性描述模糊的强弱,数值越大,就越模糊。in="SourceGraphic"定义模糊模糊的效果是对整个图像,若使用SourceAlpha,则表示模糊效果是对图像的alpha通道的,in属性除了用在结果输出之外只有这两种可选择使用的值,在其它滤镜里也是这样,下面也将会讲到。高斯模糊中的stdDeviation这个属性值描述高斯模糊的偏离大小,如果给出两个属性值,则前一个参数代表沿x轴方向的偏离值,后一个值代表沿y轴的偏离值;如果给出一个参数,则代表沿x,y轴的偏离值是一样的。上面的例子的效果如下图所示:
前面已经提到,对一个SVG图像来说,可以组合应用多个滤镜效果,下面看一个紊乱的效果:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<defs>
<filter id="Turbulence">
<feTurbulence baseFrequency="0.03 0.02" numOctaves="5" type="turbulence" result="turbulenceOutput"/>
<feComposite in="turbulenceOutput" in2="SourceAlpha" operator="in"/>
</filter>
</defs>
<path d="M193.1 79.292 C224.16 88.7968 242.127 121.499 232.627 154.414 C223.127 187.328 239.995 220.003 271.913 229.504 C303.83 239.006 336.35 218.61 345 188.876 C323.124 264.909 248.755 285.576 198.994 270.349 C149.231 255.12 98.1789 196.096 120.144 119.992 C129.376 88.0081 162.039 69.7869 193.1 79.292 zM167.341 136.242 C167.341 141.144 170.673 145.311 176.03 145.311 C181.386 145.311 184.242 140.899 184.242 136.242 C184.242 131.584 180.796 127.762 175.91 127.785 C171.025 127.809 167.341 131.339 167.341 136.242 z"
style="fill:rgb(192,192,255);stroke:rgb(130,0,61);stroke-width:1;filter:url(#Turbulence);" />
</svg>
这个例子里使用了feTurbulence和feComposite滤镜的效果,在SVG中,滤镜可以使用result和in属性进行滤镜的相互嵌套。例子中,在turbulence滤镜里使用了result="turbulenceOutput"属性,表示这个滤镜的结果要输出到别的滤镜中去,feComposite使用in="turbulenceOutput"属性来使用上一个滤镜的输出结果,由于在这个滤镜中已经使用了in属性,因此,SVG提供了in2属性供我们使用,in和in2的作用是一样的;例子中in2="SourceAlpha"属性定义了这个滤镜的单一通道;operator 属性是feComposite滤镜特有的,用来描述合成的类型,可设定over,in,out,atop,xor,arithmetic中的任一个值,大家可以替换不同的值来查看效果的变化。例子中的baseFrequency属性用来描述混沌出现的频率,有x、y两方向的值可以设置。numOctaves属性设定混沌的间隔,可选1-8,默认为1。上面例子的结果如下:
下面是一个比较复杂的例子,大家可以看看他的效果:
<svg width="100%" height="100%">
<defs>
<filter id="metallic">
<feGaussianBlur result="blurredAlpha" in="SourceAlpha" stdDeviation="3"/>
<feOffset result="offsetBlurredAlpha" in="blurredAlpha" dx="2" dy="1"/>
<feDiffuseLighting result="bumpMapDiffuse" in="blurredAlpha" surfaceScale="5" diffuseConstant="0.5" style="lighting-color:rgb(255,255,255)">
<feDistantLight azimuth="135" elevation="60"/>
</feDiffuseLighting>
<feComposite result="litPaint" in="bumpMapDiffuse" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" in2="SourceGraphic"/>
<feSpecularLighting result="bumpMapSpecular" in="blurredAlpha" surfaceScale="5" specularConstant="0.5" specularExponent="10" style="lighting-color:rgb(255,255,255)">
<feDistantLight azimuth="135" elevation="60"/>
</feSpecularLighting>
<feComposite result="litPaint" in="litPaint" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in2="bumpMapSpecular"/>
<feComposite result="litPaint" in="litPaint" operator="in" in2="SourceAlpha"/>
<feMerge>
<feMergeNode in="offsetBlurredAlpha"/>
<feMergeNode in="litPaint"/>
</feMerge>
</filter>
</defs>
<path d="M233.642 288 C249.9 265.728 318 231.266 318 195.613 C318 133.896 247.069 148.581 232.993 172.957 C218.041 147.832 149 137.805 149 195.613 C149 232.135 219.429 265.911 233.642 288 z" style="filter:url(#metallic);fill:rgb(255,38,255);stroke:rgb(11,11,13);stroke-width:1;" />
</svg>
上面的例子的结果如下:
下面我们看看渐变效果。渐变效果是指从一种颜色到另一种颜色的平滑过渡。SVG中有两种渐变方式:直线渐变和放射渐变。
直线渐变<linearGradient>有水平渐变、垂直渐变和任意角度的渐变三种情况,如果y1、y2的值相同,而x2、x2的值不同,则代表水平渐变;y1、y2不同而x1、x2相同,达标垂直渐变;如果x1、x2,y1、y2都不同,则是角度渐变。颜色可以是两种或多种颜色的组合,每种颜色都要用<stop>标记来指定,它有两个属性:stop-color和stop-opacity,分别表示颜色和透明度。
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<defs>
<linearGradient id="Linear_Gradient_Test_For_Mengxianhui" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" style="stop-color:yellow;stop-opacity:1"/>
<stop offset="50%" style="stop-color:red;stop-opacity:1"/>
<stop offset="100%" style="stop-color:blue;stop-opacity:1"/>
</linearGradient>
</defs>
<ellipse cx="200" cy="200" rx="80" ry="60" style="fill:url(#Linear_Gradient_Test_For_Mengxianhui)"/>
</svg>
上例中<linearGradient>标记定义了一个直线渐变,id属性定义该渐变的唯一标识,x1、y1定义了渐变的开始点坐标,x2、y2定义了渐变的结束点坐标,标记<stop>定义每一种颜色的信息,offset属性渐变色的开始或结束位置。该例子的结果如下:
放射渐变由<radialGradient>标记定义,例子如下:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="420" height="220">
<defs>
<radialGradient id="fade-to-black" cx="0%" cy="0%" r="20%" spreadMethod="reflect" gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:#F8C806;stop-opacity:1"/>
<stop offset="50%" style="stop-color:#000099;stop-opacity:1"/>
<stop offset="100%" style="stop-color:#458900;stop-opacity:1"/>
</radialGradient>
</defs>
<rect x="10" y="10" width="400" height="200" style="fill:url(#fade-to-black);stroke:rgb(0,0,128); stroke-width:0" />
</svg>
上面的cx,cy代表椭圆的圆心,r及rx,ry代表x方向和y方向的半径,spreadMethod代表平铺的方式,有pad,reflect和repeat三种方式。为了理解个参数的意义,您可以试着改变个参数的值,看看它们是如何控制的。该例子的结果如下:
二、在SVG中输出文字
在SVG中,文字都被看成是字符数据,所有的文字放到<text>标记中,但允许使用<tspan>标记进行嵌套,文字也是使用x,y属性在浏览器上进行定位的。例如:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<text x="100px" y="120px"
style="fill:rgb(0,0,0);font-size:36;font-family:Arial">WelCome To Mxh's Colorful World!</text>
<text x="100px" y="160px"
style="fill:rgb(255,0,0);font-size:36;font-family:Arial">http://lucky.myrice.com!</text>
</svg>
上面例子的结果如下:
SVG中的文字是放在一个不可见的矩形区域里,因此,那个矩形区域内的文字被当成一行来处理,而不是象通常的浏览器那样把文字折行显示,要显示多行文字,就必须使用多个<text>标记。当然,我们也可以对文字使用样式,fill属性定义文字的填充颜色,font-size定义文字的字号大小,font-family属性定义文字的字型,SVG中的文字样式和CSS2中的文字样式一样,也有font-style,font-stretch等属性,Web开发人员对文字的显示有了更多的选择。
文字也可以有透明度和图案填充,下面的例子是一个渐变的效果:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<defs>
<linearGradient id="violet-orange" x1="0%" y1="0%" x2="100%" y2="0%"
spreadMethod="pad" gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:rgb(216,192,216);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(175,23,87);stop-opacity:1"/>
</linearGradient>
</defs>
<rect x="49" y="29" width="450" height="41"
style="fill:rgb(0,0,0);stroke:none;stroke-width:1"/>
<text x="70px" y="56px"
style="fill:url(#violet-orange); font-size:20;font-weight:bold;font-family:Arial">Welcome to Meng Xianhui's Colorful World!</text>
</svg>
结果如下:
此外,文字也可以使用滤镜效果,下面的例子就是显示阴影效果的文字:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<defs>
<filter id="Drop_Shadow" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="150%" height="150%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blurredAlpha"/>
<feOffset in="blurredAlpha" dx="3" dy="3" result="offsetBlurredAlpha"/>
<feFlood result="flooded" style="flood-color:rgb(99,7,7);flood-opacity:0.65"/>
<feComposite in="flooded" operator="in" in2="offsetBlurredAlpha" result="coloredShadow"/>
<feComposite in="SourceGraphic" in2="coloredShadow" operator="over"/>
</filter>
</defs>
<text x="126px" y="155px" style="fill:rgb(0,0,0); font-size:30;
filter:url(#Drop_Shadow)">Welcome to Meng Xianhui's Colorful World!</text>
</svg>
结果如下:
SVG中另一个重要的概念就是文字或图像的旋转,SVG中,任何元素都可以进行旋转,下面就是旋转文字的例子:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<g style="color:#000000;font-weight:bold;font-style:normal;font-size:24">
<text x="18" y="18" transform="translate(7,7) rotate(30)">Welcome to Meng Xianhui's Colorful World!</text>
</g>
</svg>
上面例子的结果如下:
在上面的例子中使用了<g>标记,这个标记的作用是把里面的其他元素看成是一个完整的组, 和SVG中的嵌套相类似,但有一点是不同的,<g>元素允许使用transform属性,这个属性允许我们操纵其他对象的尺寸位置和形状,即可以是静态的,也可以是动态的。因此,如果你想对一个对象做旋转运动,或者做螺旋运动,或者是变形的效果,那么就可以使用transform属性,translate的值描述旋转的圆心坐标,rotate的值描述旋转的角度。
要浏览以上例子的结果,你可以把代码拷贝到记事本里,最好是拷贝到XMLSpy里,然后保存为*.svg格式,就可以直接用IE6(IE5能否浏览我没有试验)或SVG Viewer来看到效果了。保存时应该注意编码方式,SVG是基于XML的文档格式,因此,文档结构应当满足XML的格式规范(Well-Formed)的要求。
只有注册用户登录后才能发表评论。