0

I have an SVG element that's based on a circle and a mask to create a ring.

The code is as follows:

<svg width="100%" height="100%" viewBox="0 0 300 300" version="1.1">
  <defs>
    <linearGradient x1="97.3756325%" y1="100%" x2="0%" y2="100%" id="gradient">
      <stop stop-color="#FF00AC" offset="0%"></stop>
      <stop stop-color="#5D00C4" offset="100%"></stop>
    </linearGradient>
    
    <mask id="circle-mask">
      <circle cx="150" cy="150" r="145" fill="white"/>
      <circle cx="150" cy="150" r="140" fill="black"/>
    </mask>
  </defs>
  
  <circle cx="150" cy="150" r="145" mask="url(#circle-mask)" fill="url(#gradient)"/>
</svg>

The ring got a gradient as fill color. Now I want to apply a glow effect on the ring that uses the colors of the gradient. Any ideas on how to do that?

Phillipp
  • 1,425
  • 2
  • 12
  • 27

1 Answers1

3

What is a "glow"? I don't think there is a canonical definition, so I'm going with one that I have seen used before: a backdrop shadow that is colored and whose opacity values are exagerated. To define those effects, refer to the SVG <filter> spec, its support is pretty good across browsers.

I understand you need the mask for more complex situations than this one. The important thing here is the order in which different effects are applied: clip paths and masks are processed after filter effects:

First the element is styled under absence of filter effects, masking, clipping and opacity. Then the element and its descendants are drawn on a temporary canvas. In a last step the following effects are applied to the element in order: filter effects, clipping, masking and opacity.

Therefore you need to wrap the masked element in a <g> and apply the glow filter there.

Vary stdDeviation to stretch or shrink the shadow, and vary slope to change its opacity. If you set the slope to a value > 2, you will no longer get a clear border between the ring and its shadow.

<svg width="100%" height="100%" viewBox="0 0 300 300" version="1.1">
  <defs>
    <linearGradient x1="97.3756325%" y1="100%" x2="0%" y2="100%" id="gradient">
      <stop stop-color="#FF00AC" offset="0%"></stop>
      <stop stop-color="#5D00C4" offset="100%"></stop>
    </linearGradient>
    <mask id="circle-mask">
      <circle cx="150" cy="150" r="145" fill="white"/>
      <circle cx="150" cy="150" r="140" fill="black"/>
    </mask>
    <filter id="glow">
      <feGaussianBlur stdDeviation="5"/>
      <feComponentTransfer>
        <feFuncA type="linear" slope="2" />
      </feComponentTransfer>
      <feBlend in2="SourceGraphic" />
    </filter>
  </defs>
  
  <g filter="url(#glow)">      
    <circle cx="150" cy="150" r="145" mask="url(#circle-mask)" fill="url(#gradient)"/>
  </g>
</svg>
ccprog
  • 20,308
  • 4
  • 27
  • 44
  • I explicitly used the mask in my example because my real project uses a complex mask to create a specific form. When I apply your filter to my mask based example, nothing happens. – Phillipp Aug 17 '18 at 20:34
  • Nice, that works. Seems like the point was to apply it to an outer `` instead of the element itself. Thank you very much! – Phillipp Aug 17 '18 at 21:55
  • There seems to be something weird going on with that filter. When I zoom in (you can also see it without zoom) I see weird artifacts. Example: https://picload.org/view/dllidida/bildschirmfoto2018-08-20um13.2.png.html I use `stdDeviation="10"` and `slope="2"` but the settings don't really matter. – Phillipp Aug 20 '18 at 11:24
  • I can't confirm this from my setup, but I've seen these sorts of artefacts before. They seem to be triggered by specific combinations of renderers and hardware. I could speculate they have to do with slow-changing opacities, but that is pure conjecture. Nohing much I found that I could do about them. – ccprog Aug 20 '18 at 12:18