【问题标题】:Why isn't this feDisplacementMap filter working?为什么这个 feDisplacementMap 过滤器不起作用?
【发布时间】:2022-01-24 18:21:09
【问题描述】:

我正在尝试在 SVG <defs> 元素中构建图像,以用于置换贴图过滤器的 in2 属性。但是,置换贴图过滤器不会扭曲它所应用的元素。

置换贴图过滤器正在应用于网格图案,以便我可以看到置换是如何工作的:

<svg viewBox="0 0 400 400" width="400" height="400">
  <defs>
    <pattern id="grid" viewBox="0,0,10,10" width="2.5%" height="2.5%">
      <rect x="0" y="0" width="1" height="10"/>
      <rect x="0" y="0" width="10" height="1"/>
    </pattern>
  </defs>
  <rect x="0" y="0" width="400" height="400" fill="url(#grid)"/>
</svg>

我打算用作置换贴图的in2 属性的图像很复杂。当我通过过滤器中的 &lt;feImage&gt; 元素引用它并将该过滤器应用于网格图案时,我看到了我构建的图像,正如预期的那样:

<svg viewBox="0 0 400 400" width="400" height="400">
  <defs>
    <linearGradient id="gradientRed">
      <stop offset="0%" stop-color="rgba(255,0,0,0)"/>
      <stop offset="100%" stop-color="rgba(255,0,0,1)"/>
    </linearGradient>
    <linearGradient id="gradientGreen" gradientTransform="rotate(90)">
      <stop offset="0%" stop-color="rgba(0,255,0,0)"/>
      <stop offset="100%" stop-color="rgba(0,255,0,1)"/>
    </linearGradient>
    <rect id="rectRed" width="400" height="400" fill="url(#gradientRed)"/>
    <rect id="rectGreen" width="400" height="400" fill="url(#gradientGreen)"/>
    <rect id="rectBlack" width="400" height="400" fill="black"/>
    <filter id="filterIdentity">
      <feImage result="imageRed" href="#rectRed" x="0" y="0" width="400" height="400"/>
      <feImage result="imageGreen" href="#rectGreen" x="0" y="0" width="400" height="400"/>
      <feImage result="imageBlack" href="#rectBlack" x="0" y="0" width="400" height="400"/>
      <feBlend mode="screen" in="imageRed" in2="imageGreen" result="imageRedGreen"/>
      <feBlend mode="screen" in="imageRedGreen" in2="imageBlack"/>
    </filter>
    <mask id="maskCircle">
      <rect width="400" height="400" fill="black"/>
      <circle cx="200" cy="200" r="200" fill="white"/>
    </mask>
    <g id="shapeIdentity">
      <rect width="400" height="400" fill="black"/>
      <rect width="400" height="400" filter="url(#filterIdentity)" mask="url(#maskCircle)"/>
    </g>
    <filter id="filterDisplace">
      <feImage result="imageDisplace" href="#shapeIdentity" x="0" y="0" width="400" height="400"/>
    </filter>
    <pattern id="grid" viewBox="0,0,10,10" width="2.5%" height="2.5%">
      <rect x="0" y="0" width="1" height="10"/>
      <rect x="0" y="0" width="10" height="1"/>
    </pattern>
  </defs>
  <rect x="0" y="0" width="400" height="400" fill="url(#grid)" filter="url(#filterDisplace)"/>
</svg>

但是,当我使用与 &lt;feDisplacementMap&gt; 元素的 in2 属性相同的 &lt;feImage&gt; 元素时,过滤器不会扭曲它所应用的网格模式。

<svg viewBox="0 0 400 400" width="400" height="400">
  <defs>
    <linearGradient id="gradientRed">
      <stop offset="0%" stop-color="rgba(255,0,0,0)"/>
      <stop offset="100%" stop-color="rgba(255,0,0,1)"/>
    </linearGradient>
    <linearGradient id="gradientGreen" gradientTransform="rotate(90)">
      <stop offset="0%" stop-color="rgba(0,255,0,0)"/>
      <stop offset="100%" stop-color="rgba(0,255,0,1)"/>
    </linearGradient>
    <rect id="rectRed" width="400" height="400" fill="url(#gradientRed)"/>
    <rect id="rectGreen" width="400" height="400" fill="url(#gradientGreen)"/>
    <rect id="rectBlack" width="400" height="400" fill="black"/>
    <filter id="filterIdentity">
      <feImage result="imageRed" href="#rectRed" x="0" y="0" width="400" height="400"/>
      <feImage result="imageGreen" href="#rectGreen" x="0" y="0" width="400" height="400"/>
      <feImage result="imageBlack" href="#rectBlack" x="0" y="0" width="400" height="400"/>
      <feBlend mode="screen" in="imageRed" in2="imageGreen" result="imageRedGreen"/>
      <feBlend mode="screen" in="imageRedGreen" in2="imageBlack"/>
    </filter>
    <mask id="maskCircle">
      <rect width="400" height="400" fill="black"/>
      <circle cx="200" cy="200" r="200" fill="white"/>
    </mask>
    <g id="shapeIdentity">
      <rect width="400" height="400" fill="black"/>
      <rect width="400" height="400" filter="url(#filterIdentity)" mask="url(#maskCircle)"/>
    </g>
    <filter id="filterDisplace">
      <feImage result="imageDisplace" href="#shapeIdentity" x="0" y="0" width="400" height="400"/>
      <feDisplacementMap in="SourceGraphic" in2="imageDisplace" scale="20" yChannelSelector="R" xChannelSelector="G"/>
    </filter>
    <pattern id="grid" viewBox="0,0,10,10" width="2.5%" height="2.5%">
      <rect x="0" y="0" width="1" height="10"/>
      <rect x="0" y="0" width="10" height="1"/>
    </pattern>
  </defs>
  <rect x="0" y="0" width="400" height="400" fill="url(#grid)" filter="url(#filterDisplace)"/>
</svg>

这是怎么回事?

【问题讨论】:

    标签: html svg svg-filters


    【解决方案1】:

    好吧,您遇到了 Chrome 中的一个错误。这是一个在 Chrome 中工作的版本,通过将您的置换贴图图像作为一个单独的 SVG 片段内联到馈送到 feImage 的数据 URI 中。请注意这里的语法不正确 - 但正确的语法 {xlink:href = url(...)} 不起作用。 (注意 - 这在 Firefox 中不起作用,因为 Firefox 不接受 feImage 的片段引用。)

    <svg viewBox="0 0 400 400" width="400" height="400">
      <defs>
        <filter id="filterDisplace">
          <feImage result="imageDisplace" xlink:href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' width='400' height='400'%3E%3Cdefs%3E%3ClinearGradient id='gradientRed'%3E%3Cstop offset='0%25' stop-color='rgba(255,0,0,0)'/%3E%3Cstop offset='100%25' stop-color='rgba(255,0,0,1)'/%3E%3C/linearGradient%3E%3ClinearGradient id='gradientGreen' gradientTransform='rotate(90)'%3E%3Cstop offset='0%25' stop-color='rgba(0,255,0,0)'/%3E%3Cstop offset='100%25' stop-color='rgba(0,255,0,1)'/%3E%3C/linearGradient%3E%3Crect id='rectRed' width='400' height='400' fill='url(%23gradientRed)'/%3E%3Crect id='rectGreen' width='400' height='400' fill='url(%23gradientGreen)'/%3E%3Crect id='rectBlack' width='400' height='400' fill='black'/%3E%3Cfilter id='filterIdentity'%3E%3CfeImage result='imageRed' href='%23rectRed' x='0' y='0' width='400' height='400'/%3E%3CfeImage result='imageGreen' href='%23rectGreen' x='0' y='0' width='400' height='400'/%3E%3CfeImage result='imageBlack' href='%23rectBlack' x='0' y='0' width='400' height='400'/%3E%3CfeBlend mode='screen' in='imageRed' in2='imageGreen' result='imageRedGreen'/%3E%3CfeBlend mode='screen' in='imageRedGreen' in2='imageBlack'/%3E%3C/filter%3E%3Cmask id='maskCircle'%3E%3Crect width='400' height='400' fill='black'/%3E%3Ccircle cx='200' cy='200' r='200' fill='white'/%3E%3C/mask%3E%3C/defs%3E%3Crect width='400' height='400' fill='black'/%3E%3Crect width='400' height='400' filter='url(%23filterIdentity)' mask='url(%23maskCircle)'/%3E%3C/svg%3E" x="0" y="0" width="400" height="400"/>
          <feDisplacementMap in="SourceGraphic" in2="imageDisplace" scale="20" yChannelSelector="R" xChannelSelector="G"/>
        </filter>
        <pattern id="grid" viewBox="0,0,10,10" width="2.5%" height="2.5%">
          <rect x="0" y="0" width="1" height="10"/>
          <rect x="0" y="0" width="10" height="1"/>
        </pattern>
      </defs>
      <g filter="url(#filterDisplace)">
        <rect x="0" y="0" width="400" height="400" fill="url(#grid)" />
      </g>
    </svg>

    【讨论】:

    • 谢谢!以为我找到了绕过数据 URI 需求的方法,但似乎没有。
    猜你喜欢
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多