Skip to content
Advertisement

Dynamically Loading multiple External GeoJson data files and calling multiple layers dynamically using Leaflet

I have about 50 different map layers to be added on a map. Each map layer data is stored as separate JS file (lay1.js, lay2.js, …… lay50.js). Each layer have its own different properties also like Some layers may be polygons, some may be markers etc. My code is almost like as given below. Is there any way to add these .js geojson data files dynamically when the user click its corresponding layer checkbox instead of loading all as script files? Also i would like to know how to call the layers dynamically instead of storing each layer in separate variables as seen in code below.

var layer1 = L.geoJSON([lay1], {style: function (feature) {}, onEachFeature: onEachFeature}); 

Please Help. My full code is given below.

<script src="lay1.js" type="text/javascript"></script>
<script src="lay2.js" type="text/javascript"></script>
..............
..............
<script src="lay50.js" type="text/javascript"></script>

<input type="checkbox" id="1" onClick="togglejsonLayer(this);"/> Layer 1
<input type="checkbox" id="2" onClick="togglejsonLayer(this);"/> Layer 2
..............
..............
<input type="checkbox" id="50" onClick="togglejsonLayer(this);"/> Layer 50

<div id="map" style="height:600px; width:100%;"></div>

<script>
    mbAttr = '',
    mbUrl = 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=xxxxxxxxxxxxx';
var streets = L.tileLayer(mbUrl, {id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, attribution: mbAttr}),
    sattelite = L.tileLayer(mbUrl, {id: 'mapbox/satellite-v9', tileSize: 512, zoomOffset: -1, attribution: mbAttr});

var map = L.map("map", {
    center: [8.4819, 77.0361],
    zoom: 12, 
    layers: [streets]
    });         
var baseLayers = {
    "Streets": streets, 
    "Sattelite": sattelite              
    };
L.control.layers(baseLayers).addTo(map);

function onEachFeature(feature, layer) {
    var popupContent;
    if (feature.properties && feature.properties.popupContent) {
        popupContent = feature.properties.popupContent;
    }
    layer.bindPopup(popupContent);
}

var layer1 = L.geoJSON([lay1], {style: function (feature) {}, onEachFeature: onEachFeature});
var layer2 = L.geoJSON([lay2], {style: function (feature) {}, onEachFeature: onEachFeature});
..............
..............
var layer50 = L.geoJSON([lay50], {style: function (feature) {}, onEachFeature: onEachFeature});
});

var layers = [layer1, layer2, .............. ,layer50];
selId = null;
function togglejsonLayer(checkbox) {
    var checkId = checkbox.id;
    if (checkbox.checked) {
      layers[checkId - 1].addTo(map);
      selId = checkId;
      }
    else {
      map.removeLayer(layers[checkId - 1]);
      selId = null;
   }
}
</script>

Advertisement

Answer

You can fetch each geojson once you check it via the checkbox to display it on the map.

async function getGeojson(checkbox, layerName) {
    const response = await fetch(`./${layerName}.json`);
    const geojson = await response.json();
    return geojson;
}

const layers = {};
    
const togglejsonLayer = async (checkbox, layerName) => {
   const geojsonData = await getGeojson(checkbox, layerName);
   const geojson = L.geoJSON([geojsonData], { onEachFeature  });

   const checkId = checkbox.id;
   if (checkbox.checked) {
     layers[layerName] = geojson;
     layers[layerName].addTo(map);
   } else map.removeLayer(layers[layerName]);
};

You can store the geo features in an associative array (layers) once you fetch them and retrieve them via their file name (which should be unique) to be able to remove them from the map.

To remove fetching the same features again and again you can extend getGeojson to only fetch once by checking what has been stored in layers before

async function getGeojson(checkbox, layerName) {
   if (layers[layerName]) {
      if (checkbox.checked) layers[layerName].addTo(map);
      else map.removeLayer(layers[layerName]);
      return;
   }

    ...
 }

Last but not least you can remove repetitive input declaration by adding them via js. Loop over the file names and add the keys on the ids and onClick second argument respectively.

Demo

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement