Search code examples
svgleafletfill

Leaflet - multicolor pattern fill


I need to implement a multicolor fill in a polygon feature. The fill will be conditionally formatted according to feature properties.

Let's say that I need a polygon with a 3-color pattern like this:

let fillPalette = ['orange', 'green', 'blue'];

enter image description here

How is this possible in Leaflet?

In a simple div, this could be easily achieved with the following CSS function:

background: repeating-linear-gradient(
  -45deg,
  orange,
  orange 10px,
  green 10px,
  green 20px,
  blue 20px,
  blue 30px
);

However, Leaflet uses SVG/Canvas.

I am aware of the following plugins:

Unfortunately, the first doesn't seem to support multi-color patterns and the second supports only images.

Any ideas?


Solution

  • For anyone interested, here is the solution I came up with:

    When we create polygon, we set fillColor value to point to the linear-gradient we define later.

    let polygon = L.polygon(coords, {fillColor: 'url(#stripes)', fillOpacity: 1})
    

    The stripes are created using linear-gradient without color blending, like this:

    let fillPalette = ['orange', 'green', 'blue'];
    
    let gradientString = `<linearGradient id="stripes" x1="0%" y1="0%" x2="100%" y2="100%">
       <stop offset=0 stop-color=${fillPalette[0]} />
       <stop offset=33% stop-color=${fillPalette[0]} />
       <stop offset=33% stop-color=${fillPalette[1]} />
       <stop offset=66% stop-color=${fillPalette[1]} />
       <stop offset=66% stop-color=${fillPalette[2]} />
       <stop offset=100% stop-color=${fillPalette[2]} />
    </linearGradient>`
    

    Then we need to define the above linear-gradient inside the SVG. The SVG can be manipulated as following:

    let svg = document.getElementsByTagName('svg')[0];
    let svgDefs = document.createElementNS("http://www.w3.org/2000/svg", 'defs');
    svgDefs.insertAdjacentHTML('afterbegin', gradientString);
    svg.appendChild(svgDefs);
    

    Here is a working fiddle: https://jsfiddle.net/oyu60f1t/