Maurice Tempelsman
Maurice Tempelsman

Reputation: 953

Multiple Filters for Single Object in SVG

I want to put two filters on my circle. (Maybe more)

I've tried doing:

filter="url(#f1);url(#f2)"

And:

filter="url(#f1,#f2)"

And:

filter="url(#f1 #f2)"

But none of them work. How can I approach this problem?

Upvotes: 22

Views: 11622

Answers (4)

AutoBaker
AutoBaker

Reputation: 1297

Here's a below example I've been working on for a project, where I blend together 5 different layers in a single SVG. The code is slightly more tedious but it's reliable.

It's grouped into 2 darker layers, blended with a multiply mode, then 2 lighter layers blended with a screen mode.

The last filter then blends together these 2 filters using a soft-light mode, and then renders over the top of a grey base layer - useful for filling any blanks caused by opacity stops.

I have found this link very useful for determining the correct blend modes: https://oreillymedia.github.io/Using_SVG/guide/blend-modes.html or github link to the same resource is: https://github.com/oreillymedia/Using_SVG/blob/master/guide/blend-modes.html

<?xml version="1.0" standalone="yes" ?>
<!-- note: xmlns link is required to use namespaces later -->
<svg width="100px" height="100px" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <!-- define 4 different radial filters -->
        <radialGradient
            id="grad1"
            cx="0.25"
            cy="0.25"
            r="0.5"
            fx="0.25"
            fy="0.25"
            spreadMethod="pad">
            <stop offset="0%" stop-color="#900000" />
            <stop offset="100%" stop-opacity="0.0" stop-color="#900000" />
        </radialGradient>
        <radialGradient
            id="grad2"
            cx="0.75"
            cy="0.25"
            r="0.5"
            fx="0.75"
            fy="0.25"
            spreadMethod="pad">
            <stop offset="0%" stop-color="#ffffff" />
            <stop offset="100%" stop-opacity="0.0" stop-color="#ffffff" />
        </radialGradient>
        <radialGradient
            id="grad3"
            cx="0.25"
            cy="0.75"
            r="0.5"
            fx="0.25"
            fy="0.75"
            spreadMethod="pad">
            <stop offset="0%" stop-color="#bfbfff" />
            <stop offset="100%" stop-opacity="0.0" stop-color="#bfbfff" />
        </radialGradient>
        <radialGradient
            id="grad4"
            cx="0.75"
            cy="0.75"
            r="0.5"
            fx="0.75"
            fy="0.75"
            spreadMethod="pad">
            <stop offset="0%" stop-color="#009000" />
            <stop offset="100%" stop-opacity="0.0" stop-color="#009000" />
        </radialGradient>
        
        <!-- define a base rectangle at 50% grey -->
        <rect id="rect-base" x="0" y="0" width="100" height="100" fill="#ff0000" />
        
        <!-- define 4 rectangles and apply above filters to each one -->
        <rect id="grad1-rect" x="0" y="0" width="100" height="100" fill="url(#grad1)"/>
        <rect id="grad2-rect" x="0" y="0" width="100" height="100" fill="url(#grad2)"/>
        <rect id="grad3-rect" x="0" y="0" width="100" height="100" fill="url(#grad3)"/>
        <rect id="grad4-rect" x="0" y="0" width="100" height="100" fill="url(#grad4)"/>

        <!-- define a filter which combines the two darker gradient filled rectangles -->
        <filter id="fil-dark" x="0%" y="0%" height="100%" width="100%">
            <feImage xlink:href="#grad1-rect" result="fil-1A" x="0" y="0" />
            <feImage xlink:href="#grad4-rect" result="fil-1B" x="0" y="0" />
            <feBlend in="fil-1A" in2="fil-1B" mode="multiply" result="blendedGrad1"/>
            <feComposite in="blendedGrad1" in2="SourceGraphic" operator="in"/>
        </filter>
        
        <!-- define a filter which combines the two lighter gradient filled rectangles -->
        <filter id="fil-light" x="0%" y="0%" height="100%" width="100%">
            <feImage xlink:href="#grad2-rect" result="fil-2A" x="0" y="0" />
            <feImage xlink:href="#grad3-rect" result="fil-2B" x="0" y="0" />
            <feBlend in="fil-2A" in2="fil-2B" mode="screen" result="blendedGrad2"/>
            <feComposite in="blendedGrad2" in2="SourceGraphic" operator="in"/>
        </filter>
        
        <!-- define 2 rectangles that are filled with the light and dark filter results -->
        <rect id="filter1-rect" filter="url(#fil-dark)" x="0" y="0" width="100" height="100"/>
        <rect id="filter2-rect" filter="url(#fil-light)" x="0" y="0" width="100" height="100"/>
        
        <!-- define a final filter which combines the two rectangles which each contain the result of another filter -->
        <filter id="fil-blend" x="0%" y="0%" height="100%" width="100%">
            <feImage xlink:href="#filter1-rect" result="fil-3A" x="0" y="0" />
            <feImage xlink:href="#filter2-rect" result="fil-3B" x="0" y="0" />
            <feBlend in="fil-3A" in2="fil-3B" mode="soft-light" result="blendedGrad3"/>
            <feComposite in="blendedGrad3" in2="SourceGraphic" operator="in"/>
        </filter>
        
    </defs>
    
    <!-- create a base layer rectangle filled with 50% grey -->
    <rect x="0" y="0" width="100" height="100" fill="#7f7f7f"/>
    <!-- add a second rectangle on top filled with the final filter result -->
    <rect filter="url(#fil-blend)" x="0" y="0" width="100" height="100"/>
</svg>

Took me a bit of working out so hopefully it might be useful to someone else.

Upvotes: 1

karly
karly

Reputation: 404

I know this is a very old question, but for people referencing this, you can also just separate your filter functions with spaces - filter="url(#f1) url(#f2)" should work

See: https://css-tricks.com/almanac/properties/f/filter/

Upvotes: 23

Badger Cat
Badger Cat

Reputation: 966

You could add multiple effects in one filter, however if you want to stack the filters up, first group the object and then apply the other filter to your object.

<g filter="url(#f2)">
<rect width="90" height="90" stroke="green" stroke-width="3" fill="yellow" filter="url(#f1)"/>
</g>

Upvotes: 22

Robert G
Robert G

Reputation: 79

Start with an identity feColorMatrix and name the result currentGraphic for example. Use that as 'in' for each filter element bundle/transaction start and as 'result' for the final operation of the bundle. The next element bundle picks it up at 'in'='currentGraphic', etc.

Upvotes: 7

Related Questions