Home > Mobile >  SVG - mask feGaussianBlur with radialGradient
SVG - mask feGaussianBlur with radialGradient

Time:11-16

I want to blur an image's corners, while retaining a sharp center. Using css backdrop-blur() is out of question, because Firefox does not support it. Adding a sharp image on top of a blurry one and then masking the first one out is not feaseable aswell, as in the end I want to change the static image with a three.js scene.

I tried to follow this tutorial, but with a radial gradient, rather than a fixed bar.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <filter id="blurlayer" width="100%" height="100%">
            
          <feGaussianBlur stdDeviation="4" result="blur"/>
            
          <radialGradient id="radialGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%" result="mask">
            <stop offset="0%" stop-color="white" stop-opacity="1" />
            <stop offset="100%" stop-color="black" stop-opacity="0" />
          </radialGradient>
            
          <feComposite in="blur" in2="mask" operator="in" result="comp" />
            
          <feMerge result="merge">
            <feMergeNode in="SourceGraphic" />
            <feMergeNode in="comp" />
          </feMerge> 
        </filter>
      </defs>

      <image filter="url(#blurlayer)" x="0" y="0" width="100%" height="100%"   xlink:href="https://www.wildtextures.com/wp-content/uploads/wildtextures-grey-felt-texture.jpg"/>
    </svg>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

It does not work. Could somebody please help me find out why? I set up a codepen, if that helps anyone.

CodePudding user response:

You have to do a little more work than that - you can't drop a radialGradient in the middle of a filter - only filter primitives are allowed inside a filter and you need to import any image/shape you want to use via feImage.

Also, when masking via feComposite/in - the "in" operator only uses the alpha channel (unlike actual masks that use luminance) - so you can use a black/black gradient with a variable opacity.

Lastly, because Firefox doesn't support fragment identifiers inside feImage, if you want FF support, you have to define your mask in the content and import the image you want to use via feImage. This makes the filter not reusable, but if this is once off content that's fine. If you do want to use this filter more generally, then you can define a gradient-filled rect and then convert it in to a full SVG image that you then inline via a data:uri inside a feImage. This is more work (and I always seem to get the escaping rules for svg xml data URI's wrong) - so I didn't do it here.

FWIW - that tutorial is both complete and correct.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        
        <radialGradient id="radialGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%" result="mask">
            <stop offset="0%" stop-color="black" stop-opacity="1" />
            <stop offset="100%" stop-color="black" stop-opacity="0" />
        </radialGradient>
            
        
        <filter id="blurlayer" x="0%" y="0%" width="100%" height="100%">
          <feImage xlink:href="https://www.wildtextures.com/wp-content/uploads/wildtextures-grey-felt-texture.jpg" width="100%" height="100%" result="original-image" preserveAspectRatio="none"/>         
          <feComposite in="original-image" in2="SourceGraphic" operator="in" result="unblurred" />  
          
     <feGaussianBlur in="original-image" stdDeviation="4" result="blurred-image"/>
          <feComponentTransfer in="SourceGraphic" result="invertlight">
                <feFuncA type="table" tableValues="1 0"/>
          </feComponentTransfer>
          <feComposite in="blurred-image" operator="in"/>
          
          <feComposite operator="over" in="unblurred"/>
        </filter>
      </defs>
  
<g filter="url(#blurlayer)">
      <rect fill="url(#radialGradient)" x="0" y="0" width="100%" height="100%"/>
</g>
    </svg>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related