[GIS] Leaflet Omnivore – KML fill and stroke colors are always the default blue

kmlleafletmapbox

I'm trying to import kml file and style them.

In my KML, we have different styles for example

<Style id="YellowPolyStyle">
        <LabelStyle>
            <color>00000000</color>
            <scale>0</scale>
        </LabelStyle>
        <BalloonStyle>
        </BalloonStyle>
        <LineStyle>
            <color>ff6e6e6e</color>
            <width>0.4</width>
        </LineStyle>
        <PolyStyle>
            <color>ff00d9ff</color>
        </PolyStyle>
    </Style>
    <Style id="GreenPolyStyle">
        <LabelStyle>
            <color>00000000</color>
            <scale>0</scale>
        </LabelStyle>
        <BalloonStyle>
        </BalloonStyle>
        <LineStyle>
            <color>ff6e6e6e</color>
            <width>0.4</width>
        </LineStyle>
        <PolyStyle>
            <color>ff009961</color>
        </PolyStyle>
    </Style>

And I calling those style for filling my KML layer. Here is my sample

<Placemark id="ID_00000">
  <name>Grid ID: 14</name>
  <Snippet maxLines="0"></Snippet>
  <description></description>
  <styleUrl>#GreenPolyStyle</styleUrl>
  .......
</Placemark>

But it is not working. It is filling default Blue colour in the KML layer.

So how can I fix this issue. I am using Leaflet Omnivore library for loading the KML.

I manually tried to attach style using setStyle function but it is also not working. Here is my sample code

var runLayer = omnivore.kml(kml)
  .on('ready', function() {
      runLayer.eachLayer(function(layer) {
      if(layer.feature.properties.styleUrl == "#YellowPolyStyle") {
              layer.setStyle(
                  { 
                    "LabelStyle": {
                      "color": "00000000",
                      "scale": "0"
                    },
                    "BalloonStyle": "",
                    "LineStyle": {
                      "color": "ff6e6e6e",
                      "width": "0.4"
                    },
                    "PolyStyle": { "color": "ff00d9ff" }
                  }
              );
        }

How can this be done?

Best Answer

You are almost there.

Unfortunately, Leaflet does not handle complex style sets as in KML format. It looks like in KML, you can specify a family of styles for label, line string, balloon / marker, etc.

Whereas in Leaflet, each feature is styled with an individual spec. Therefore the object that you pass to setStyle is not understood by Leaflet. You have to determine first the geometry type (i.e. marker, line string, etc.) and give the corresponding style directly:

runLayer.eachLayer(function (layer) {
  if (layer.feature.properties.styleUrl === '#PolyStyleOGreen') {
    if (layer.feature.geometry.type === 'LineString') {
      // See Leaflet path layers options
      // http://leafletjs.com/reference-1.0.3.html#path
      layer.setStyle({
        color: '#ff6e6e6e', // More red than green and blue => redish color
        weight: 4 
      });
    } else {
      console.log('unknown geometry type');
    }
  } else {
    console.log('unknown styleUrl');
  }
});

Demo: https://plnkr.co/edit/nJMXrUYp5tzmHuVZn2lm?p=preview

See the path options for available style options in Leaflet.

BTW, you could slightly simplify your code by directly passing a custom GeoJSON layer group as 3rd argument of omnivore.kml, and specifying its style option, so that the layers that are built directly get the appropriate style, instead of having to loop through them afterwards to re-style them.

For example:

var myCustomGroup = L.geoJSON(null, {
    style: getStyle
});

function getStyle(feature) {
    if (feature.properties.styleUrl === '#PolyStyleOGreen') {
        if (feature.geometry.type === 'LineString') {
            return {
                color: '#ff6e6e6e',
                weight: 4
            }
        }
    }
}

omnivore.kml('test.kml', null, myCustomGroup).addTo(map);

Updated demo: https://plnkr.co/edit/dJKqyCZn7jOXM9zJfY9u?p=preview