How to get rid of extraneous <feFlood/> in filter

45 views Asked by At

I'm using filters with my rounded rects and notice that the paints the whole sub-region and I can't figure out how to remove it so that all I have is a rounded rect of a different color based on my filters.

<svg viewBox="0 0 350 100" width="350" height="100">
    <defs>
        <filter id="1_opacitySolidFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" result="opacitySolidLayer"/>
            <feBlend in="opacitySolidLayer" in2="SourceGraphic" mode="multiply"/>
        </filter>
        <filter id="2_solidOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="solidOpacityLayer"/>
            <feBlend in="solidOpacityLayer" in2="SourceGraphic" mode="multiply"/>
        </filter>
        <filter id="3_opacitySOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="opacityOpacityLayer"/>
            <feBlend in="opacityOpacityLayer" in2="SourceGraphic" mode="multiply"/>
        </filter>
    </defs>
    <rect id="1" x="0" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#1_opacitySolidFilter)" fill="#4472C4"/>
    <rect id="2" x="125" rx="20" width="100" height="100" filter="url(#2_solidOpacityFilter)" fill="#4472C4"/>
    <rect id="3" x="250" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#3_opacitySOpacityFilter)" fill="#4472C4"/>
</svg>

The result I need is these newly colored round rects, but without the lime-green bleed of the <feFlood/>.

Each of these rects has an opacity value on the rect, the flood in the its filter, or both. I did try using an <feComposite/> with operator="in" after each <feBlend/> but that only works if my rect fill doesn't have an opacity value (i.e. the final color isn't changed).

But that <feComposite/> changes the color of the 1st and 3rd rounded rect when there is an opacity value on the rect. See for example:

<svg viewBox="0 0 350 100" width="350" height="100">
    <defs>
        <filter id="1_opacitySolidFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" result="opacitySolidLayer"/>
            <feBlend in="opacitySolidLayer" in2="SourceGraphic" mode="multiply" result="blended1"/>
            <feComposite in="blended1" in2="SourceGraphic" operator="in"/>
        </filter>
        <filter id="2_solidOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="solidOpacityLayer"/>
            <feBlend in="solidOpacityLayer" in2="SourceGraphic" mode="multiply" result="blended2"/>
            <feComposite in="blended2" in2="SourceGraphic" operator="in"/>
        </filter>
        <filter id="3_opacitySOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="opacityOpacityLayer"/>
            <feBlend in="opacityOpacityLayer" in2="SourceGraphic" mode="multiply" result="blended3"/>
            <feComposite in="blended3" in2="SourceGraphic" operator="in"/>
        </filter>
    </defs>
    <rect id="1" x="0" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#1_opacitySolidFilter)" fill="#4472C4"/>
    <rect id="2" x="125" rx="20" width="100" height="100" filter="url(#2_solidOpacityFilter)" fill="#4472C4"/>
    <rect id="3" x="250" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#3_opacitySOpacityFilter)" fill="#4472C4"/>
</svg>

Does anyone know how I can remove the extra lime green flood that fills the corners to have a rounded rect, but not change the color (i.e. keep the color of the rounded rects like in the first example)?

1

There are 1 answers

0
ccprog On

The best I can come up with is to increase opacity of the source grafic to 1, using that as the destination for the "in" compositing. It can be achieved, a bit akwardly, with the <feComponentTransfer> primitive. The problem is that you need to produce a function where

result α = 0 where source α = 0 and
           1 where source α > 0

<feFuncA type="linear" slope="10"/> will only set the resulting opacity to 1 for a source opacity > 0.1. If you expect to have lower opacities in your source grafics, the slope value might need to be set higher.

<svg viewBox="0 0 350 100" width="350" height="100">
    <defs>
        <filter id="1_opacitySolidFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" result="opacitySolidLayer"/>
            <feBlend in="opacitySolidLayer" in2="SourceGraphic" mode="multiply" result="blended"/>
            <feComponentTransfer in="SourceGraphic" result="solid">
              <feFuncA type="linear" slope="10"/>
            </feComponentTransfer>
            <feComposite in="blended" in2="solid" operator="in"/>
        </filter>
        <filter id="2_solidOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="solidOpacityLayer"/>
            <feBlend in="solidOpacityLayer" in2="SourceGraphic" mode="multiply" result="blended"/>
            <feComponentTransfer in="SourceGraphic" result="solid">
              <feFuncA type="linear" slope="10"/>
            </feComponentTransfer>
            <feComposite in="blended" in2="solid" operator="in"/>
        </filter>
        <filter id="3_opacitySOpacityFilter" color-interpolation-filters="sRGB" x="0" y="0" width="100%" height="100%">
            <feFlood flood-color="#0F0" flood-opacity="0.5" result="opacityOpacityLayer"/>
            <feBlend in="opacityOpacityLayer" in2="SourceGraphic" mode="multiply" result="blended"/>
            <feComponentTransfer in="SourceGraphic" result="solid">
              <feFuncA type="linear" slope="10"/>
            </feComponentTransfer>
            <feComposite in="blended" in2="solid" operator="in"/>
        </filter>
    </defs>
    <rect id="1" x="0" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#1_opacitySolidFilter)" fill="#4472C4"/>
    <rect id="2" x="125" rx="20" width="100" height="100" filter="url(#2_solidOpacityFilter)" fill="#4472C4"/>
    <rect id="3" x="250" rx="20" width="100" height="100" fill-opacity="0.5" filter="url(#3_opacitySOpacityFilter)" fill="#4472C4"/>
</svg>