svg-filters - feDisplacementMap 在生成的矩形上不起作用

标签 svg-filters css-filters

我正在尝试创建一个 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/

相关文章:

svg - 阻止 SVG feSpecularLighting 过滤器填充 <rect> 元素之外

不同域上的 Firefox SVG 过滤器

javascript - 使用 javascript 动态修改 SVG 过滤器

css - 在 chrome 中更改滤镜时图像在悬停时移动

css - 将十六进制或 rgb 颜色转换为 fecolormatrix 值

javascript - 触发补间动画以单独悬停在 SVG 六边形上

css - 过滤器 : blur not working on MS Edge

css - 在 css 或 svg 中创建圆形运动模糊

html - 替代灰度滤镜 CSS3

javascript - jQuery 在过滤器的先前内联样式之上添加内联样式