如何在 SVG 蒙版中使用动画滤镜?

How to use an animated filter in an SVG mask?

我尝试在蒙版上使用动画滤镜 noise 来蒙版元素,但没有成功。遮罩本身有效,但我无法让动画在遮罩中工作,即使动画本身有效。

我已经尝试了 feColorMatrix(单通道,仅 alpha,各种组合)和蒙版的亮度和 alpha 类型的所有可能组合,但没有任何结果。

如有任何帮助,我们将不胜感激!

<svg width="200" height="200" viewBox="0 0 200 200"
    xmlns="http://www.w3.org/2000/svg">
    <defs>
        <filter id="noise" x="0" y="0" width="100%" height="100%">
            <feTurbulence type="fractalNoise" baseFrequency="0.01" seed="12345" />
            <feColorMatrix type="hueRotate" values="0">
                <animate attributeName="values" from="0" to="360" dur="5s" repeatCount="indefinite" />
            </feColorMatrix>
            <feColorMatrix type="matrix" values="0 0 0 1 0  0 0 0 1 0  0 0 0 1 0  1 0 0 0 0  " />
        </filter>
        <mask id="Mask">
            <rect x="0" y="0" width="100%" height="100%" filter="url(#noise)" />
        </mask>
    </defs>
    
    <rect x="0" y="0" width="200" height="200" fill="green" />
    <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />
</svg>

编辑:

多亏了 Michael,它几乎可以正常工作了。这是更新后的代码,本质上我正在尝试合并两个图像,底部是完整图像,顶部图像具有 alpha 并且是透明的。它有效,但噪声在图像顶部仍然可见,即使蒙版本身有效(尽管由于可见噪声而很难看到)。

<svg width="960" height="1200" viewBox="0 0 960 1200"
    xmlns="http://www.w3.org/2000/svg">
    <defs>
        <filter id="noise" x="0" y="0" width="100%" height="100%">
            <feTurbulence type="fractalNoise" baseFrequency="0.005" seed="1" />
            <feColorMatrix type="hueRotate" values="0">
                <animate attributeName="values" from="0" to="360" dur="5s" repeatCount="indefinite" />
            </feColorMatrix>
            <feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  1 0 0 0 0" result="opacity-mask"/>
            <feComposite operator ="in" in2="opacity-mask"/>
            <feComposite operator="over" in2="SourceGraphic"/>
        </filter>
        <filter id="dropshadow">
            <feGaussianBlur in="SourceAlpha" stdDeviation="20" />
            <feOffset dx="5" dy="5" result="offsetblur" />
            <feFlood flood-color="#000" flood-opacity="1" result="offsetColor"/>
            <feComposite in="offsetColor" in2="offsetblur" operator="in" result="offsetblur"/>
            <feComposite operator="over" in2="SourceGraphic"/>
        </filter>
    </defs>
    
    <image href="https://martinhoura.net/svg/img_bottom.jpg" width="100%" x="0%" y="0" />
    <g filter="url(#noise)">
        <image href="https://martinhoura.net/svg/img_top.png" width="100%" x="0" y="0" filter="url(#dropshadow)" />
    </g>
</svg>

动画滤镜在 Chrome 和 Safari 中与图案、蒙版和剪辑结合使用时可能会出现问题。您可以通过使用 feComposite/in.

在过滤器中执行掩码来解决此问题

<svg width="200" height="200" viewBox="0 0 200 200"
    xmlns="http://www.w3.org/2000/svg">
    <defs>
        <filter id="noise" x="0" y="0" width="100%" height="100%">
            <feTurbulence type="fractalNoise" baseFrequency="0.01" seed="12345" />
            <feColorMatrix type="hueRotate" values="0">
                <animate attributeName="values" from="0" to="360" dur="5s" repeatCount="indefinite" />
            </feColorMatrix>
            <feColorMatrix type="matrix" values="0 0 0 1 0  0 0 0 1 0  0 0 0 1 0  1 0 0 0 0" result="opacity-mask"/>
            <feFlood flood-color="green"/>
            <feComposite operator ="in" in2="opacity-mask"/>
            <feComposite operator="over" in2="SourceGraphic"/>
        </filter>
    </defs>
    
    <rect x="0" y="0" width="200" height="200" fill="red" filter="url(#noise)" />
</svg>

更新:

感谢您发布相关代码,因为这里的问题不同。

您的实施存在两个问题。首先是您在 feComposite/in 中使用 SourceGraphic 作为 Turbulence 的掩码 - 所以出现了湍流,而不是 SourceGraphic - 您需要将 'in2' 更改为 'in'.

但更大的问题是您将原始图像的 variably-transparent 版本叠加在 fully-opaque 原始图像之上。这样做的结果就是原始图像。如果你想显示任何效果,你需要让你的底层图像 semi-opaque 。这是我的意思的一个夸张的例子。

<svg width="960" height="1200" viewBox="0 0 960 1200"
    xmlns="http://www.w3.org/2000/svg">
    <defs>
        <filter id="noise" x="0" y="0" width="100%" height="100%">
            <feTurbulence type="fractalNoise" baseFrequency="0.005" seed="1" />
            <feColorMatrix type="hueRotate" values="0">
                <animate attributeName="values" from="0" to="360" dur="5s" repeatCount="indefinite" />
            </feColorMatrix>
            <feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  1 0 0 0 0" result="opacity-mask"/>
            <feComposite operator="in" in="SourceGraphic"/>
        </filter>
      
      <filter id="half-opacity">
        <feColorMatrix type="matrix" values="1 0 0 0 0 
                                             0 1 0 0 0 
                                             0 0 1 0 0 
                                             0 0 0 0.25 0"/>
      </filter>

    </defs>
    
    <image filter="url(#half-opacity") href="https://martinhoura.net/svg/img_bottom.jpg" width="100%" x="0%" y="0" />
    <g filter="url(#noise)">
        <image href="https://martinhoura.net/svg/img_top.png" width="100%" x="0" y="0" />
    </g>
</svg>