2

I'm using Leaflet with Leaflet-KML plugin to show a KML file with multiple polygons. In this KML file there are 125 polygons. I want to pick only one to show on the map. The choice is made directly via the url (for example if I want to show the polygon named "Territorio 001" the url will be something like /map?n=001). Now, I can include, load and show the entire KML, but I can't figure out how I can "select" only one polygon to show, and hide the others.

This is my code for loading and showing the basemap and KML:

    <script type="text/javascript">
            // Make basemap
        const key = 'xxx';
        const map = L.map('map').setView([0, 0], 1);
        const gl = L.maplibreGL({
            style: `https://api.maptiler.com/maps/1cc7120b-9404-449d-8aca-dfcde7b44b89/style.json?key=${key}`
        }).addTo(map);

        map.attributionControl.setPrefix('');

            // Load kml file
        fetch('doc.kml')
        .then(res => res.text())
        .then(kmltext => {
                    // Create new kml overlay
            const parser = new DOMParser();
            const kml = parser.parseFromString(kmltext, 'text/xml');
            const track = new L.KML(kml);
            map.addLayer(track);

                    // Adjust map to show the kml
            const bounds = track.getBounds();
            map.fitBounds(bounds);
        });
    </script>

And this is a part of my KML (I have included only the structure deleting some similar lines):

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>Nuova Mappa Residenziale</name>
    <description/>
    <Style id="poly-006064-1000-77-nodesc-highlight">
      <LineStyle>
        <color>ff646000</color>
        <width>1.5</width>
      </LineStyle>
      <PolyStyle>
        <color>4d646000</color>
        <fill>1</fill>
        <outline>1</outline>
      </PolyStyle>
      <BalloonStyle>
        <text><![CDATA[<h3>$[name]</h3>]]></text>
      </BalloonStyle>
    </Style>
    ...
    <StyleMap id="poly-006064-1000-77-nodesc">
      <Pair>
        <key>normal</key>
        <styleUrl>#poly-006064-1000-77-nodesc-normal</styleUrl>
      </Pair>
      <Pair>
        <key>highlight</key>
        <styleUrl>#poly-006064-1000-77-nodesc-highlight</styleUrl>
      </Pair>
    </StyleMap>
    <Folder>
      <name>Fucecchio Alto 001-014</name>
      <Placemark>
        <name>Territorio 001</name>
        <styleUrl>#poly-880E4F-1000-77-nodesc</styleUrl>
        <Polygon>
          <outerBoundaryIs>
            <LinearRing>
              <tessellate>1</tessellate>
              <coordinates>
                10.80684,43.72934,0
                ...
              </coordinates>
            </LinearRing>
          </outerBoundaryIs>
        </Polygon>
      </Placemark>
      <Placemark>
        <name>Territorio 002</name>
        <styleUrl>#poly-A52714-1000-77-nodesc</styleUrl>
        <Polygon>
          <outerBoundaryIs>
            <LinearRing>
              <tessellate>1</tessellate>
              <coordinates>
                10.806808,43.734096,0
                ...
              </coordinates>
            </LinearRing>
          </outerBoundaryIs>
        </Polygon>
      </Placemark>
    </Folder>
    <Folder>
      <name>Fucecchio Nord 015-025</name>
      <Placemark>
        <name>Territorio 015</name>
        <styleUrl>#poly-FF5252-1000-77-nodesc</styleUrl>
        <Polygon>
          <outerBoundaryIs>
            <LinearRing>
              <tessellate>1</tessellate>
              <coordinates>
                10.801615,43.736216,0
                ...
              </coordinates>
            </LinearRing>
          </outerBoundaryIs>
        </Polygon>
      </Placemark>
3
  • From your code it seems you are not using leaflet-omnivore plugin but leaflet-kml plugin.
    – TomazicM
    Apr 12, 2023 at 8:53
  • Hi @TomazicM, you're right. I have tried different plugin, so maybe I'm litte bit confused on which I'm using now. Do you think using Omnivore can help me instead of this one? Apr 12, 2023 at 11:26
  • 1
    Yes, see answer.
    – TomazicM
    Apr 12, 2023 at 13:44

1 Answer 1

1

It turns out that leaflet-kml plugin does not offer possibility to access KML placemark attributes/properties name or description to filter layer by their values.

Here leaflet-omnivore plugin comes to rescue since it makes possible KML layer to be loaded through GeoJSON layer, where name or description are exposed as feature properties. This allows filtering with the help of GeoJSON layer .filter option.

To show only KML placemark with 'Territorio 002' name, relevant part of the code could look something like this:

var geoJsonLayer = L.geoJSON(null, {
  filter: function(feature) {
    return(feature.properties.name == 'Territorio 002');
  },
  onEachFeature: function(feature, layer) {
    if (feature.properties.name) {
      layer.bindPopup(feature.properties.name);
    }
  }
});

var kmlLayer = omnivore.kml('doc.kml', null, geoJsonLayer)
  .on('ready', function() {
    map.fitBounds(kmlLayer.getBounds());
  })
  .addTo(map);
4
  • Thank you, now I have only one polygon. But I have another problem: the shape is not the original color, it's blue. There is a way to read the style from KML? Or I need to set manually? Apr 12, 2023 at 14:13
  • 1
    The above is answer to your question. If answer helped you solve your problem, it's customary on GIS SE site to mark it as accepted, to let others with similar problems know that problem was resolved. If you have additional question, please post it as a separate question, otherwise it can go like this ad infinitum in comments.
    – TomazicM
    Apr 12, 2023 at 14:18
  • If I want to show two or more polygons, based on feature.properties.name like the example above, how can I do it? Apr 14, 2023 at 8:30
  • Modify GeoJSON layer filter option function to return true for desired polygons.
    – TomazicM
    Apr 14, 2023 at 8:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.