【问题标题】:feDisplacementMap on generated rectangle not working生成的矩形上的 feDisplacementMap 不起作用
【发布时间】:2019-12-06 00:29:42
【问题描述】:

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

现在对于置换贴图的完整示例,过滤器似乎没有任何效果:

.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 元素边界框的百分比,因此不能选择删除此属性。但是我是在这里遇到浏览器错误还是我错过了什么?

【问题讨论】:

    标签: svg-filters css-filters


    【解决方案1】:

    两个小错误。您需要在第二次洪水的 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>

    【讨论】:

    • 谢谢!现在我意识到我还有另一个问题:如果我需要对过滤器的某些部分使用像素单位,而对其他部分使用百分比怎么办?例如,位移的比例应该是绝对的,但是 in2 矩形当然应该填充整个过滤器空间。由于 SVG 本身的维度为零(只有 HTML 元素有),我被卡住了吗?
    • 显然将尺寸与用户原始单位混合在 Firefox 上效果很好,但在 Chrome 上效果不佳。查看我在这里创建的完整过滤器codepen.io/RothDerek/pen/qeRGLZ?editors=1100
    • 在 SVG 1.1 中,您不能在同一个过滤器中混合维度类型 - 但您可以将效果拆分到两个过滤器并将其中一个过滤器应用于 元素包装器。
    • 好的,我没有找到在过滤器中使用 的方法,也许我遗漏了一些东西。在 CSS 中应用 SVG 过滤器似乎比纯 SVG 复杂一些...
    • 啊。对不起。忘记了您在 HTML 而不是 SVG 内容上使用它。对于 CSS/HTML,您将定义两个过滤器并将一个应用于内部 div,另一个应用于外部 div。但是,对于您的特定用例,没有简单的方法可以在一个过滤器中构造置换贴图并在另一个过滤器中进行置换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 2022-01-24
    • 2017-02-19
    • 2012-04-02
    相关资源
    最近更新 更多