[GIS] Add svg filter to paths created by leaflet

leafletsvg

If I were to create a simple inline svg, I could modify paths to have a drop shadow or a blur by creating a <filter> within a <defs> grouping. However, Leaflet dynamically generates the SVGs it uses to display paths, and I'm not sure how to add a filter after the fact.

Failed Ideas:

  • I've tried using jQuery to append a defs to the SVG after the fact:

Like this:

    $("svg").prepend("<defs><filter id='dropshadow' height='130%'><feGaussianBlur in='SourceAlpha' stdDeviation='3'/> <!-- stdDeviation is how much to blur --> <feOffset dx='2' dy='2' result='offsetblur'/> <!-- how much to offset --><feMerge><feMergeNode/> <!-- this contains the offset blurred image --><feMergeNode in='SourceGraphic'/> <!-- this contains the element that the filter is applied to --></feMerge></filter></defs>");

And then specify the location of the defs in my CSS, like this:

    filter: url("../index.html#dropshadow");
  • Have the <defs> / filter definition already inline in the html above the map element, and then reference the filter definition from the svg via a the CSS filter URL.

My code (inline above the leaflet map div):

    <svg xmlns="w3.org/2000/svg"; version="1.1">
        <defs>
            <filter id='dropshadow' height='130%'>
                <feGaussianBlur in='SourceAlpha' stdDeviation='3'/> <!-- stdDeviation is how much to blur --> 
                <feOffset dx='2' dy='2' result='offsetblur'/> <!-- how much to offset -->
                <feMerge><feMergeNode/> <!-- this contains the offset blurred image -->
                <feMergeNode in='SourceGraphic'/> <!-- this contains the element that the filter is applied to --></feMerge>
            </filter>
        </defs>
    </svg>

Best Answer

I'd suggest going with your second approach of putting your svg markup in-line. I think your jQuery prepend method doesn't work because you need to create <defs> and other children of <svg> elements using document.createElementNS and jQuery is probably using document.createElement.

Anyway, the piece you're missing is applying your filter to your svg, which you could do two ways.

CSS approach:

div.leaflet-overlay-pane svg > g path {
  filter: url(#dropshadow);
}

$ approach (put this after you add your geojson to your map):

$("div.leaflet-overlay-pane svg > g path").css({
  filter: "url(#dropshadow)"
}); 
Related Question