我正在尝试创建一个 SVG 过滤器,它将图像水平“切成”两半,并将下部部分向右移动几个像素。该过滤器将在 CSS 中使用。 为此,我在一个由 2 个 feFlood 合并在一起生成的矩形上使用 feDisplacementMap。
这就是我生成位移图使用的矩形的方法。我认为它是正确生成的:
.container {
outline: 1px solid green;
}
h1 {
filter: url(#displacementFilter);
}
<div class="container">
<h1>test</h1>
</div>
<svg width="0" height="0" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter" x="-10%" y="-10%" width="120%" height="120%" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
<!-- red channel for displacement, other channels neutral -->
<feFlood flood-color="rgb(255,128,128)" flood-opacity="0.5" result="rect-red" x="0%" y="50%" width="100%" height="50%"/>
<!-- all channels neutral for no displacement -->
<feFlood flood-color="rgb(128,128,128)" flood-opacity="0.5" result="rect-blue" x="0" y="0%" width="100%" height="50%"/>
<feMerge result="rect">
<feMergeNode in="rect-red"/>
<feMergeNode in="rect-blue"/>
</feMerge>
</filter>
</svg>
现在对于带有displacementMap的完整示例,过滤器似乎没有任何效果:
.container {
outline: 1px solid green;
}
h1 {
filter: url(#displacementFilter);
}
<div class="container">
<h1>test</h1>
</div>
<svg width="0" height="0" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter" x="-10%" y="-10%" width="120%" height="120%" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
<!-- building the in2 rectangle for the displacement map -->
<feFlood flood-color="rgb(255,128,128)" flood-opacity="0.5" result="rect-red" x="0%" y="50%" width="100%" height="50%"/>
<feFlood flood-color="rgb(128,128,128)" flood-opacity="0.5" result="rect-blue" x="0" y="0%" width="100%" height="50%"/>
<feMerge result="rect">
<feMergeNode in="rect-red"/>
<feMergeNode in="rect-blue"/>
</feMerge>
<!--
applying the displacement.
Depending on the scale, sometimes the source graphic
completely disappears
-->
<feDisplacementMap in2="rect" in="SourceGraphic" scale="10" xChannelSelector="R" yChannelSelector="G" result="displacement"/>
<!-- merging the rectangle and the displacement just to show the effect -->
<feMerge>
<feMergeNode in="rect"/>
<feMergeNode in="displacement"/>
</feMerge>
</filter>
</svg>
但是如果我从过滤器中删除 primitiveUnits 属性,我就可以使位移正常工作:
.container {
outline: 1px solid green;
}
h1 {
filter: url(#displacementFilter);
}
<div class="container">
<h1>test</h1>
</div>
<svg width="0" height="0" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter" x="-10%" y="-10%" width="120%" height="120%" filterUnits="objectBoundingBox">
<feFlood flood-color="rgb(255,128,128)" flood-opacity="0.5" result="rect-red" x="0%" y="50%" width="100%" height="50%"/>
<feFlood flood-color="rgb(128,128,128)" flood-opacity="0.5" result="rect-blue" x="0" y="0%" width="100%" height="50%"/>
<feMerge result="rect">
<feMergeNode in="rect-red"/>
<feMergeNode in="rect-blue"/>
</feMerge>
<feDisplacementMap in2="rect" in="SourceGraphic" scale="10" xChannelSelector="R" yChannelSelector="G" result="displacement"/>
<feMerge>
<feMergeNode in="rect"/>
<feMergeNode in="displacement"/>
</feMerge>
</filter>
</svg>
据我了解,我需要将 PrimitiveUnits 属性设置为“objectBoundingBox”,否则我无法使用原始 HTML 元素边界框的百分比,因此不能选择删除此属性。但是我在这里遇到了浏览器错误还是我错过了一些东西?
最佳答案
两个小错误。您需要在第二次洪水的 x 中输入 %。
result="rect-blue" x="0%" y="0%" width="100%" height="50%"
位移基元中的比例也需要是 objectBoundingBox - 所以 0.1(但这非常大 - 所以我将其更改为下面的 0.01,以便您可以实际看到发生了什么)。
<feDisplacementMap in2="rect" in="SourceGraphic" scale=".01" xChannelSelector="R" yChannelSelector="G" result="displacement"/>
一般来说,最好将 objectBoundingBox 尺寸表示为小数 - Firefox 至少在某一时刻不接受百分比。而且最好在文档中定义过滤器,使其高于将应用到的 HTML(至少在某一时刻,Safari 无法找到过滤器,如果您这样做的话)。
.container {
outline: 1px solid green;
}
h1 {
filter: url(#displacementFilter);
}
<svg width="0" height="0" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter" x="0%" y="0%" width="100%" height="100%" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
<!-- building the in2 rectangle for the displacement map -->
<feFlood flood-color="rgb(255,128,128)" flood-opacity="0.5" result="rect-red" x="0" y="0.5" width="1" height="0.5"/>
<feFlood flood-color="rgb(128,128,128)" flood-opacity="0.5" result="rect-blue" x="0" y="0" width="1" height="0.5"/>
<feMerge result="rect">
<feMergeNode in="rect-red"/>
<feMergeNode in="rect-blue"/>
</feMerge>
<!--
applying the displacement.
Depending on the scale, sometimes the source graphic
completely disappears
-->
<feDisplacementMap in2="rect" in="SourceGraphic" scale="0.01" xChannelSelector="R" yChannelSelector="G" result="displacement"/>
<!-- merging the rectangle and the displacement just to show the effect -->
<feMerge>
<feMergeNode in="rect"/>
<feMergeNode in="displacement"/>
</feMerge>
</filter>
</svg>
<div class="container">
<h1>MY AMAZING TEST TEXT</h1>
</div>
关于svg-filters - feDisplacementMap 在生成的矩形上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57240740/