Search code examples
svgsvg-filters

discard all SourceGraphic colors/alpha and recolor?


I have a shape with a stroke. The fill is orange with 50% opacity (so alpha = .5 and rgb(255,112,0)) and the stroke is blue (no transparency).

Using filters, I've been trying to make a copy (similar to a drop shadow, but without the blur). I'd like the copy to be solid orange.

But I just can't seem to get this as feColorMatrix continues to use SourceGraphic values.

No idea why, but if my shape fill is no transparency, and I also use feComponentTransfer again, I can get the solid shape copy.

The shape on the right is the one I'd like to make solid orange (or any color and opacity I choose), regardless of shape/stroke fill/opacity.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="960" height="540" class="slide" shape-rendering="geometricPrecision" fill-rule="evenodd">
      <rect width="960" height="540" stroke="#385D8A" fill="white" stroke-width="3" class="testSlideBorder" />

      <svg x="10" y="10" overflow="visible" stroke="#0000FF" stroke-miterlimit="8" stroke-width="4">
        <defs>
        <filter id="offsetColoredShape" height="500%" width="500%" x="-275%" y="-275%">
         <feColorMatrix in="SourceAlpha" type="matrix" values="
                                        0 0 0 0 1 
                                        0 0 0 0 0.439
                                        0 0 0 0 0 
                                        0 0 0 1 0"
                                       result="changeToOrangeFill"/>

    	<feComponentTransfer result="changedAgain">
            <feFuncR type="linear" slope="1" />
            <feFuncG type="linear" slope="0.439" />
            <feFuncB type="linear" slope="0" />
            <feFuncA type="linear" slope="1" />
</feComponentTransfer>

    	<feOffset dx="120"/>
	    </filter>               
  </defs>
<use xlink:href="#star" filter="url(#offsetColoredShape)" />
        <path id="star" fill="rgb(255,112,0)" fill-opacity="0.5" d="M0,63.904L17.609,51.5L8.562,31.952L30.014,30.014L31.952,8.562L51.5,17.609L63.904,0L76.309,17.609L95.857,8.562L97.795,30.014L119.247,31.952L110.199,51.5L127.809,63.904L110.199,76.309L119.247,95.857L97.795,97.795L95.857,119.247L76.309,110.199L63.904,127.809L51.5,110.199L31.952,119.247L30.014,97.795L8.562,95.857L17.609,76.309Z" />
      </svg>

    </svg>

Notice in the <path/> that fill-opacity="0.5". If I change that to fill-opacity="1", it works as expected. Here's what that looks like:

      <svg x="10" y="10" overflow="visible" fill="#4472C4" stroke="#0000FF" stroke-miterlimit="8" stroke-width="4">
        <defs>
        <filter id="offsetColoredShape" height="500%" width="500%" x="-275%" y="-275%">
         <feColorMatrix in="SourceAlpha" type="matrix" values="
                                        0 0 0 0 1 
                                        0 0 0 0 0.439
                                        0 0 0 0 0 
                                        0 0 0 1 0"
                                       result="changeToOrangeFill"/>

    	<feComponentTransfer result="changedAgain">
            <feFuncR type="linear" slope="1" />
            <feFuncG type="linear" slope="0.439" />
            <feFuncB type="linear" slope="0" />
            <feFuncA type="linear" slope="1" />
        </feComponentTransfer>

    	<feOffset dx="120"/>
	    </filter>               
        </defs>
        <use xlink:href="#star" filter="url(#offsetColoredShape)" />
        <path id="star" fill="rgb(255,112,0)" fill-opacity="1" d="M0,63.904L17.609,51.5L8.562,31.952L30.014,30.014L31.952,8.562L51.5,17.609L63.904,0L76.309,17.609L95.857,8.562L97.795,30.014L119.247,31.952L110.199,51.5L127.809,63.904L110.199,76.309L119.247,95.857L97.795,97.795L95.857,119.247L76.309,110.199L63.904,127.809L51.5,110.199L31.952,119.247L30.014,97.795L8.562,95.857L17.609,76.309Z" />
      </svg>
That's what I'm after no matter the shapes fill opacity.

Any thoughts as to how I can get a solid color (like black) and alpha = 100% of the SourceGraphic, and then be able to modify the color and it's opacity to any color/opacity I like?


Solution

  • You're not setting the alpha to 100% in your original feColorMatrix - you're multiplying the alpha by 1. If you want to set alpha to 100% - you should set the fifth column to 1 (not the fourth column).

    Now the problem with that is that it sets all the background to 100% opacity as well so you get the rest of the graphic colored solid black.

    But - we have a hack to get around this. Instead of using SourceAlpha - use SourceGraphic, and use the first three columns of the alpha row to boost the alpha of just the colored pixels to 100%. The result is a little crispy (because we nuke anti-aliasing) - but it does get you what you want and works for every color - including rgb(1,1,1).

    If you know your colors are not going to be that close to black then, you can dial down those 255's to something more reasonable (like 5 or 10) & retain at least some of the anti-aliasing.

          <svg x="10" y="10" overflow="visible" stroke="#0000FF" stroke-miterlimit="8" stroke-width="4" style="background:grey" color-interpolation-filters="sRGB">
            <defs>
            <filter id="offsetColoredShape" height="500%" width="500%" x="-275%" y="-275%">
             <feColorMatrix in="SourceGraphic" type="matrix" values="
                                            0 0 0 0 1 
                                            0 0 0 0 0.439
                                            0 0 0 0 0 
                                            255 255 255 1 0"
                                           result="changeToOrangeFill"/>
    
    
        	<feOffset dx="80"/>
    	    </filter>               
      </defs>
    <use xlink:href="#star" filter="url(#offsetColoredShape)" />
            <path id="star" fill="rgb(255,112,0)" fill-opacity="0.5" d="M0,63.904L17.609,51.5L8.562,31.952L30.014,30.014L31.952,8.562L51.5,17.609L63.904,0L76.309,17.609L95.857,8.562L97.795,30.014L119.247,31.952L110.199,51.5L127.809,63.904L110.199,76.309L119.247,95.857L97.795,97.795L95.857,119.247L76.309,110.199L63.904,127.809L51.5,110.199L31.952,119.247L30.014,97.795L8.562,95.857L17.609,76.309Z" />
          </svg>