将模糊滤镜应用于SVG图像的特定区域

10

我有一个相当复杂的、动态创建的svg图像,是使用jQuery SVG创建的。我想创建一个“弹出窗口”区域,位于画布中所有svg元素的顶部。为了创造现代半透明的iOS7外观,我想对弹出窗口下面的所有内容应用模糊滤镜。我希望能够动态设置此弹出窗口区域的x、y、宽度和高度属性。

请看这个例子

<svg width="500" height="500">
    <rect x="10" y="10" height="235" width="235" fill="red" />
    <rect x="255" y="10" height="235" width="235" fill="green" />
    <rect x="10" y="255" height="235" width="235" fill="blue" />
    <rect x="255" y="255" height="235" width="235" fill="yellow" />

    <rect x="50" y="50" height="400" width="400" fill="rgba(255,255,255,0.8)" />
</svg>
在这种情况下,所有被白色区域覆盖的内容都应该被模糊处理。然后它应该看起来像这样: Example 我已经找到了这个,但这里使用的是静态背景图片,而我没有。 是否有任何方法可以使用svg、css和jQuery实现这种效果?
2个回答

13

这个方案怎么样?稍微有些难用,但它似乎在所有浏览器上都能运行。

http://jsfiddle.net/J3X4p/2/

<svg x="0px" y="0px" width="500px" height="500px" viewbox="0 0 500 500">
  <defs>
    <filter id="blurry" x="0%" y="0%" height="100%" width="100%" primitiveUnits="userSpaceOnUse">
      <feGaussianBlur x="50" y="50" width="400" height="400" stdDeviation="40" in="SourceGraphic" result="blurSquares"/>
      <feComponentTransfer in="blurSquares" result="opaqueBlur">
        <feFuncA type="linear" intercept="1"/>
      </feComponentTransfer>
      <feBlend mode="normal" in="opaqueBlur" in2="SourceGraphic"/>
    </filter>
  </defs>

  <g id="squares" filter="url(#blurry)">
    <rect x="10" y="10" height="235" width="235" fill="red" />
    <rect x="255" y="10" height="235" width="235" fill="green" />
    <rect x="10" y="255" height="235" width="235" fill="blue" />
    <rect x="255" y="255" height="235" width="235" fill="yellow" />
  </g>

    <rect x="50" y="50" height="400" width="400" fill="rgb(255,255,255)" fill-opacity="0.8" />
</svg>

由于过滤器应用于背景而不是<rect>,因此这更加棘手。 为了使其起作用,您必须将<rect>中的xywidthheight复制到feGaussianBlur原语中。


太棒了!这个非常有效!非常感谢,我的团队会对这个结果非常满意!=) - Dafen
另一个问题:如果筛选器下面没有元素,它就会变成纯黑色。有没有办法使用svg元素后面的背景?(将css背景图像设置为html标记) 如果不行,我将尝试在筛选器下方显示html背景图像的副本,但在其他svg元素上方。 - Dafen
只有当浏览器支持enable-background和BackgroundImage时才能使用。但是,正如Michael已经指出的那样,大多数浏览器都不支持。如果支持的话,你应该使用他的解决方案而不是我的。 - Paul LeBeau

3
这只有在单个浏览器(Internet Explorer 10)中,使用内联SVG才能直接实现 - 您可以使用“enable-background”属性并使用内置的“BackgroundImage”源。这是您链接到教程文本中显示的方法。
如果您的背景仅为图像,则有一种解决方法。您编写一个过滤器,使用feImage过滤器来拉取与背景中相同的图像,对它们进行模糊处理,并将模糊处理放在您想要在其上显示内容下面。这是您链接到教程实际代码中使用的方法。
如果您的背景是其他SVG内容(文本,路径等),则没有跨浏览器的方法可以实现您的效果,因为Firefox不支持将SVG对象作为feImage过滤器基元的输入。如果您不关心Firefox,那么您可以使用该教程针对图像使用的相同解决方法。
以下是后一种情况的示例 - 它非常接近您想要的,但我只在Chrome / Windows中测试过(我知道它在Firefox中无法工作)。
<svg x="0px" y="0px" width="500px" height="500px" viewbox="0 0 500 500">
  <defs>
    <filter id="blurry" x="-20%" y="-20%" height="140%" width="140%" primitiveUnits="userSpaceOnUse">
      <feImage x="0" y="0" width="500" height="500" xlink:href="#squares" result="mySquares"/>
      <feGaussianBlur stdDeviation="40" in="mySquares" result="blurSquares"/>
      <feComponentTransfer in="blurSquares" result="morealpha">
        <feFuncA type="linear" intercept=".8"/>
      </feComponentTransfer>
      <feComposite operator="in" in="morealpha" in2="SourceGraphic" result="clipBlur"/>
      <feFlood x="10%" y="10%" width="80%" height="80%" flood-color="white" flood-opacity="0.6" result="whitesquare"/>
      <feBlend mode="screen" in="clipBlur" in2="whitesquare"/>
    </filter>
  </defs>

  <g id="squares">
    <rect x="10" y="10" height="235" width="235" fill="red" />
    <rect x="255" y="10" height="235" width="235" fill="green" />
    <rect x="10" y="255" height="235" width="235" fill="blue" />
    <rect x="255" y="255" height="235" width="235" fill="yellow" />
  </g>

    <rect filter="url(#blurry)" x="50" y="50" height="400" width="400" fill="rgb(255,255,255)" />
</svg>

在此输入图像描述

(更新:最近发现 - 您可以使用JavaScript将要提供给feImage的任何内容编码为svg+xml编码的数据URI,然后跨浏览器使用它。非常丑陋。)


谢谢你的回答!我采用了BigBadaboom的方法,因为Firefox对我们非常重要。=) - Dafen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接