SVG 2D入门10 - 滤镜

    滤镜称得上是SVG最强大的功能了,它容许你给图形(图形元素和容器元素)添加各类专业软件中才有的滤镜特效。这样你就很容易在客户端生成和修改图像了。并且滤镜并无破坏原有文档的结构,因此维护性也很好。
      滤镜用filter元素定义;须要使用的时候,在须要滤镜效果的图形或容器上添加filter属性,引用相关滤镜便可。
      滤镜元素包含不少的滤镜原子操做;每一个原子操做在传入的对象上执行一个基本的图形操做,并产生图形输出。大多数的原子操做生成的结果基本都是一个RGBA图片。每一个原子操做的输入既能够是源图形,也可使其余原子操做的结果。因此引用滤镜效果的过程就是在源图形上应用相关的滤镜原子操做,最后生成一个新的图形并渲染。
      当在容器上(例如g元素)使用filter属性的时候,滤镜效果会应用到容器中的全部元素。可是容器中的元素并不会直接渲染到屏幕,而是会被暂时存储起来。而后,图形命令会被当作处理引用的filter元素的过程的一部分被执行,这个时候才会去渲染。这是经过使用SourceGraphic和SourceAlpha来指定的。下面的第二个例子中的第三种状况会演示这种效果。
      有些滤镜效果会生成一些没有定义的像素点,这些点会被处理成透明效果。
先来看一个例子:浏览器

复制代码
<svg width="7.5cm" height="5cm" viewBox="0 0 200 120"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <title>SVG 滤镜效果示例</title>
  <desc>采用各类滤镜效果实现一副图形的3D的光照效果。</desc>
  <defs>
    <filter id="MyFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="120">
      <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
      <feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
      <feSpecularLighting in="blur" surfaceScale="5" specularConstant=".75" 
                          specularExponent="20" lighting-color="#bbbbbb"  
                          result="specOut">
        <fePointLight x="-5000" y="-10000" z="20000"/>
      </feSpecularLighting>
      <feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut"/>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" 
                   k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
      <feMerge>
        <feMergeNode in="offsetBlur"/>
        <feMergeNode in="litPaint"/>
      </feMerge>
    </filter>
  </defs>
  <rect x="1" y="1" width="198" height="118" fill="#888888" stroke="blue" />
  <g filter="url(#MyFilter)" >
 <g>
      <path fill="none" stroke="#D90000" stroke-width="10" 
            d="M50,90 C0,90 0,30 50,30 L150,30 C200,30 200,90 150,90 z" />
      <path fill="#D90000" 
            d="M60,80 C30,80 30,40 60,40 L140,40 C170,40 170,80 140,80 z" />
      <g fill="#FFFFFF" stroke="black" font-size="45" font-family="Verdana" >
        <text x="52" y="76">SVG</text>
      </g>
    </g>
  </g>
</svg>
复制代码

      这个例子运行在FireFox上的效果是最后一幅图的结果:缓存

注意:在其余的浏览器中可能会有一些不一样。
      这个滤镜使用了6个效果,依次是(单步效果图如上图所示:):
    feGaussianBlur:这一步是进行高斯模糊处理;该特效的输入是源图片的透明度值,输出存到了临时缓冲blur中。blur值做为了下面feOffset和feSpecularLighting的输入。
    feOffset:这一步是把图片平移一些位置;该特效的输入是上一步中生成的blur,生成一个新的缓存offsetBlur。
    feSpecularLighting:这一步是把图片的表面进行光线的处理。输入是第一步中生成的blur,输出存放到新的缓存specOut中。
    两次feComposite:这两步是对不一样的缓存层进行组合。
    feMerge:这一步是合并不一样的层。该步一般是最后的一步,融合各个缓存的层,生成最终的图片,并渲染呈现。虽然这一步也能够用屡次feComposite特效完成,可是毕竟仍是不太方便。svg


filter元素与滤镜效果区域
      滤镜效果区域指的是滤镜效果起做用的区域。这个区域的大小是由filter元素下列的属性定义的:
filterUnits = "userSpaceOnUse | objectBoundingBox"
      这个属性定义了x,y,width和height使用的坐标空间。与其余的Unit相关的属性同样,该属性也是两个值:userSpaceOnUse和objectBoundingBox(默认值)。
  userSpaceOnUse表示使用引用该filter元素的元素的用户坐标系统。
  objectBoundingBox表示使用引用该filter元素的元素的包围盒的百分比作取值范围。url

x,y,width,heightspa

      这些属性定义了滤镜起做用的矩形区域。滤镜效果不会应用在超过这个区域的点上。x,y的默认值是-10%,width与height的默认值是120%。code

filterResorm

      该属性定义了中间缓存区域的大小,因此也定义了缓存图片的质量。一般状况下,不须要提供这个值,浏览器本身会选取合适的值。一般,滤镜效果区域应该定义成和背景正好能点和点一一对应,这样会带来必定的效率优点。xml

      除了这些属性,filter元素的下列属性也很重要:
primitiveUnits = "userSpaceOnUse | objectBoundingBox"
      这个属性定义每一个原子操做中坐标和长度使用的坐标空间,这个属性的取值仍是userSpaceOnUse和objectBoundingBox。只不过默认值是userSpaceOnUse。对象

xlink:href = "<iri>"
      该属性用于在当前filter元素中引用其余的filter元素。blog

      值得注意的是,filter元素只会继承本身的父节点的属性,并不会继承引用该filter元素的元素的属性。

 

滤镜总览
      各类滤镜原子操做就不详述了,须要的时候查看官方文档便可。下面看一下这些操做的共性。除了"in"属性,下面的其余属性是全部原子操做均可用的。
x,y,width,height
      这几个属性很少说了,它定义了滤镜原子起做用的区域,不妨成为"滤镜子区域"吧。这几个属性是受filter元素的做用区域限制的,默认状况下,取值分别是0,0,100%,100%。这些原子的做用区域超过filter元素的做用区域都不起做用。
result
      存放该步操做的结果。指定了result之后,同一个filter元素的其余后续操做均可以用in来指定其为输入。这个参看上面的例子就知道了。若是省略了这个值,则只能做为紧挨着的下一步操做的隐式输入,注意若是紧挨着的下一步操做已经用in指定了输入,则以in指定的为准。
in
      表示该步操做的输入。省略in属性的话,将会默认使用前一步的结果做为本步的输入,若是省略的是第一步的in,则会使用"SourceGraphic"做为值(参看下面的说明)。in属性能够引用前面result存放的值,也能够指定下面6个特殊的值:
SourceGraphic:这个值表明使用当前的图形元素做为操做的输入。
SourceAlpha:这个值表明使用当前图形元素的Alpha值做为操做的输入。
BackgroundImage:这个值表明使用当前的背景截图做为操做的输入。
BackgroundAlpha:这个值表明使用当前的背景截图的Alpha值做为操做的输入。
FillPaint:这个值使用当前图形元素的fill属性的值做为操做的输入。
StrokePaint:这个值使用当前图形元素的stroke属性的值做为操做的输入。

    这些值中 BackgroundImage和BackgroundAlpha可能比较难以理解,下面重点看看这两个值。 

 

访问背景截图
      一般状况下,咱们能够直接使用引用filter元素的元素的背景截图做为filter效果的源图片。表明这种输入的取值是BackgroundImage和BackgroundAlpha,前一个包含颜色和Alpha值,后一个只包含Alpha值。为了支持这种使用方式,还须要在引用filter元素的元素上显式的开启这个特性,这须要设置元素的enable-background属性。
enable-background = "accumulate | new [ <x> <y> <width> <height> ] | inherit"
      这个属性只能用于容器元素,它定义了如何去截取背景截图。
      new值表明:容许该容器的子元素访问容器的背景截图,而且该容器的子元素会渲染到背景中和设备上。
      accumulate是默认值,它的效果取决于上下文:若是父辈容器元素使用了enable-background:new的话,那么该容器的全部图形元素都会参与背景的渲染。不然,说明父辈容器没有准备截取背景截图,该元素的图形元素显示只显示在设备上。
      下面的例子演示了这些取值的效果:

复制代码
<svg width="13.5cm" height="2.7cm" viewBox="0 0 1350 270"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <title>使用背景截图的例子</title>
  <desc>下面几个例子解释了不一样状况下背景截图的使用状况</desc>

  <defs>
    <filter id="ShiftBGAndBlur" 
            filterUnits="userSpaceOnUse" x="0" y="0" width="1200" height="400">
      <desc>这个滤镜舍弃了源图片,而是使用背景截图</desc>
      <feOffset in="BackgroundImage" dx="0" dy="125" />
      <feGaussianBlur stdDeviation="8" />
    </filter>
    <filter id="ShiftBGAndBlur_WithSourceGraphic" 
            filterUnits="userSpaceOnUse" x="0" y="0" width="1200" height="400">
      <desc>这个滤镜特效同时融合了背景截图和当前元素的图片</desc>
      <feOffset in="BackgroundImage" dx="0" dy="125" />
      <feGaussianBlur stdDeviation="8" result="blur" />
      <feMerge>
        <feMergeNode in="blur"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <g transform="translate(0,0)">
    <desc>第一幅是没加滤镜的效果</desc>
    <rect x="25" y="25" width="100" height="100" fill="red"/>
    <g opacity=".5">
      <circle cx="125" cy="75" r="45" fill="green"/>
      <polygon points="160,25 160,125 240,75" fill="blue"/>
    </g>
    <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/>
  </g>

  <g enable-background="new" transform="translate(270,0)">
    <desc>第二幅是在容器上使用滤镜效果</desc>
    <rect x="25" y="25" width="100" height="100" fill="red"/>
    <g opacity=".5">
      <circle cx="125" cy="75" r="45" fill="green"/>
      <polygon points="160,25 160,125 240,75" fill="blue"/>
    </g>
    <g filter="url(#ShiftBGAndBlur)"/>
    <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/>
  </g>

  <g enable-background="new" transform="translate(540,0)">
    <desc>第三幅是在内部容器上使用滤镜效果,注意与第二幅图的不一样</desc>
    <rect x="25" y="25" width="100" height="100" fill="red"/>
    <g filter="url(#ShiftBGAndBlur)" opacity=".5">
      <circle cx="125" cy="75" r="45" fill="green"/>
      <polygon points="160,25 160,125 240,75" fill="blue"/>
    </g>
    <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/>
  </g>

  <g enable-background="new" transform="translate(810,0)">
    <desc>第四幅是在图形元素上使用滤镜效果</desc>
    <rect x="25" y="25" width="100" height="100" fill="red"/>
    <g opacity=".5">
      <circle cx="125" cy="75" r="45" fill="green"/>
      <polygon points="160,25 160,125 240,75" fill="blue"
               filter="url(#ShiftBGAndBlur)"/>
    </g>
    <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/>
  </g>

  <g enable-background="new" transform="translate(1080,0)">
    <desc>第五幅是在图形元素上使用不一样的滤镜效果</desc>
    <rect x="25" y="25" width="100" height="100" fill="red"/>
    <g opacity=".5">
      <circle cx="125" cy="75" r="45" fill="green"/>
      <polygon points="160,25 160,125 240,75" fill="blue"
               filter="url(#ShiftBGAndBlur_WithSourceGraphic)"/>
    </g>
    <rect x="5" y="5" width="260" height="260" fill="none" stroke="blue"/>
  </g>
</svg>
复制代码

      效果图以下(第一排是最终效果图,第二排是滤镜效果):

      这个例子包含5个部分:
  1.第一组中的图片,没用使用任何滤镜效果。
  2.第二组使用同样的图片,可是开启了使用背景的效果。
  3.第三组使用同样的图片,可是在内部的容器了使用了滤镜效果。
  4.第四组在内容容器的元素上使用了滤镜效果。
  5.最后一组使用了与第四组相同的滤镜效果并合并源图片后生成的效果。

 

      滤镜的概念其实很简单,只不过是每一个效果的代码看起来比较复杂,其实咱们试一下就很清楚了,不过因为不一样的浏览器对SVG的支持程度都不同,具体的效果仍是本身试试后再使用吧。 

相关文章
相关标签/搜索