SVG filter effects examples

Flame

import gsap from "gsap"
import { useEffect } from "react"

export default () => {
    useEffect(() => {
        const feTurbulence = document.querySelector('#e-turbulence > feTurbulence')
        const feDisplacementMap = document.querySelector('#e-turbulence > feDisplacementMap')
        const progress = { current: 0 }
        gsap.to(progress, {
            current: 1,
            duration: 3,
            yoyo: true,
            ease: 'none',
            repeat: -1,
            onUpdate() {
                feTurbulence.setAttribute('baseFrequency', 0.005 + progress.current / 200)
            }
        })
    }, [])

    return <div style={{width: 300, height: 200, overflow: 'hidden'}}>
        <svg style={{display: 'none'}}>
            <filter id="e-turbulence">
                <feTurbulence result="fe-turbulence" baseFrequency="0.02" numOctaves="2" />
                <feDisplacementMap xChannelSelector="R" yChannelSelector="G" result="fe-displacement-map" scale="16" in="SourceGraphic"/>
            </filter>
        </svg>
        <img src="https://taterboom.com/assets/posts/svg-filter-effects/fire.webp" alt="" style={{ filter: "url(#e-turbulence)", margin: -16, maxWidth: 'unset'}} width="332" height="232"/>
    </div>
}

Gooey

import gsap from "gsap"
import { useEffect } from "react"

export default () => {
    useEffect(() => {
        gsap.to(document.querySelector('#up'), {
            y: -30,
            duration: 2,
            repeat: -1,
            yoyo: true,
        })
        gsap.to(document.querySelector('#down'), {
            y: 30,
            duration: 2,
            repeat: -1,
            yoyo: true,
        })
    }, [])
    return <div style={{ filter: "url(#goo)" }}>
        <svg style={{display: 'none'}}>
            <filter id="goo">
                {/* blur to make edge pixels alpha < 1  */}
                <feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="10" />
                {/* make the pixels with <1 alpha be opaque */}
                <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 20 -10" result="goo" />
            </filter>
        </svg>
        <div id="up" style={{ width: 128, height: 128, background: 'red', borderRadius: 999}}></div>
        <div id="down" style={{ width: 128, height: 128, background: 'green', borderRadius: 999, marginTop: -40}}></div>
    </div>
}

Light and Shadow

export default () => {
    return <div>
        <svg style={{ height: 1 }}>
            <filter id="felight">
                {/* blur the source image to make bump map less sharp */}
                <feGaussianBlur stdDeviation="3" />
                {/* create bump map based on alpha channel */}
                <feColorMatrix type="luminanceToAlpha" result="bumpMap" />
                {/* use bump map for lighting filter */}
                <feDiffuseLighting in="bumpMap" surfaceScale="3">
                    <fePointLight x="225" y="150" z="30"></fePointLight>
                </feDiffuseLighting>
                {/* compose the lighting result with source image using multiplication */}
                <feComposite in2="SourceGraphic" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
                {/* not <feBlend in2="SourceGraphic" mode="multiply" /> */}
            </filter>
        </svg>
        <img style={{ filter: "url(#felight)" }} src="https://taterboom.com/assets/posts/svg-filter-effects/stoneroad.jpeg" width="332" height="232" onMouseMove={e => {
            document.querySelector('#felight fePointLight').setAttribute('x', e.nativeEvent.offsetX)
            document.querySelector('#felight fePointLight').setAttribute('y', e.nativeEvent.offsetY)
        }}/>
    </div>
}