kaktus
kaktus

Reputation: 189

Masking SVG-filter, not simply combining mask and filter

I am attempting to apply fractalNoise filter to HTML element. However, I dont want the whole element to be affected but to have the filter gradually increase from bottom to top. In order to achieve this, I tried to first create the noise filter and to then pair it with a mask filter.

I run into two problems: The first but probably smaller one is that the filtered element is appearing on top of the unfiltered one.

The second problem is that my idea does not seem to work out at all: The mask filter simply makes the element fade. I guess the reason is that I do not apply the mask to the noise filter but simply apply both the noise and the mask filter to the element. Unfortunately, this was the only tutorial I found online as this procedure works well with masked blur filters.

This is what my filter looks like:

<filter id="noiselayer" width="200%" height="200%">

    <feTurbulence type="fractalNoise" baseFrequency="0.0001 0.2" numOctaves="1" result="warp"></feTurbulence>
    <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="30" in="SourceGraphic" in2="warp" result="noise"/>

    <feImage id="feimage" xlink:href="data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxOTIwIDEwODAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE5MjAgMTA4MDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCgkuc3Qwe2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KPC9zdHlsZT4NCjxnIGlkPSJWZXJsYXVmIj4NCgk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ijk2MCIgeTE9IjEwODAiIHgyPSI5NjAiIHkyPSItMi43Mjg0ODRlLTEyIj4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0ZGRkZGRjtzdG9wLW9wYWNpdHk6MCIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMDAwMDAwIi8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cmVjdCB4PSIwIiB5PSIwIiBjbGFzcz0ic3QwIiB3aWR0aD0iMTkyMCIgaGVpZ2h0PSIxMDgwIi8+DQo8L2c+DQo8L3N2Zz4=" width= "100%" result="mask" />

    <feComposite in2="mask" in="noise"  operator="in" result="comp" />

    <feMerge result="merge">
        <feMergeNode in="SourceGraphic" />
        <feMergeNode in="comp" />
    </feMerge> 

Here is a sad JSFiddle to illustrate the problem: https://jsfiddle.net/ew09thnx/11/

I am grateful for any hint how to solve it!

Upvotes: 2

Views: 915

Answers (1)

Michael Mullany
Michael Mullany

Reputation: 31705

The key thing to understand here is that feComposite operator="in" uses opacity, not luminance to perform its masking function, so you need to convert that gradient from a black/white gradient to an all black with variable opacity gradient. You can do this with feColorMatrix/luminanceToAlpha.

If you just want to create some noise and layer it over another element, then this is a better way to do it. (changed your baseFrequency value to something more noticeable).

(I've never seen a filter defined in a head element before - I hope that works cross browser - and I don't understand why you're applying it to the HTML element vs. the body element.)

<filter id="noiselayer" width="200%" height="200%">

      <feTurbulence result="fNoise" type="fractalNoise" numOctaves="6" baseFrequency="1.98"/> 
      <feColorMatrix in="fNoise" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 7 -3" result="noise"/>

      <feImage id="feimage" xlink:href="data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iRWJlbmVfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxOTIwIDEwODAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE5MjAgMTA4MDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCgkuc3Qwe2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KPC9zdHlsZT4NCjxnIGlkPSJWZXJsYXVmIj4NCgk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ijk2MCIgeTE9IjEwODAiIHgyPSI5NjAiIHkyPSItMi43Mjg0ODRlLTEyIj4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0ZGRkZGRiIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMDAwMDAwIi8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cmVjdCB4PSIwIiB5PSIwIiBjbGFzcz0ic3QwIiB3aWR0aD0iMTkyMCIgaGVpZ2h0PSIxMDgwIi8+DQo8L2c+DQo8L3N2Zz4=" width= "100%"  />
      <feColorMatrix type="luminanceToAlpha" result="mask"/>

      <feComposite in2="mask" in="noise"  operator="in" result="comp" />

      <feMerge result="merge">
        <feMergeNode in="SourceGraphic" />
        <feMergeNode in="comp" />
      </feMerge> 

    </filter>

Upvotes: 4

Related Questions