如何在 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>
我尝试在蒙版上使用动画滤镜 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>