I need to dynamically change layers on a leaflet map on click, having two GeoJSON files, one for states and other for cities, like a dashboard.
When clicking a state it should zoom to the clicked state, remove states layer and show only the cities that are within that state, which could be done filtering by a attribute (STATE_NAME in case) in cities geojson that refers to the state it belongs.
I'm starting from the sample code from Leaflet tutorial of choropleth map https://leafletjs.com/examples/choropleth/ which already have the zoom on click function.
Starting from the sample from leaflet website, I managed to add a filter inside the cities geojson and then defined a function that selects only the cities of a specific state, just to know that it works, now I'm struggling to make that filter work dinamically, from the state I clicked. I dont know what should I aim to achieve this, if its using layer groups or something else.
Both cities and states are polygons. Cities geojson have the attributes CITY_NAME, STATE_NAME and VARNAME as a numeric value used by cloropeth map. States geojson have also STATE_NAME attribute.
I uploaded both geojson and the html file that works with them at the following Gist: https://gist.github.com/caduguedess/86caa8f04fe9335e6ef4dc62cc4f6c0b
var states = L.geoJson(states, {
style,
onEachFeature,
}).addTo(map);
/* citiesData */
var geojson = L.geoJson(cities, {
style,
onEachFeature,
/* filter: selection
*/ }).addTo(map);
/* function selecao(feature) {
if (feature.properties.CITY_NAME === "Malanje") return true
} */
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
map.attributionControl.addAttribution('Population data © <a href="http://census.gov/">US Census Bureau</a>');
const legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
const div = L.DomUtil.create('div', 'info legend');
const grades = [0, 10, 20, 50, 100, 200, 500, 1000];
const labels = [];
let from, to;
for (let i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
labels.push(`<i style="background:${getColor(from + 1)}"></i> ${from}${to ? `–${to}` : '+'}`);
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);
Best Answer
There are a few things that have to be taken care of to make it work like you want:
mouseover
,mouseout
andclick
processing function for each of them.info.update
call result must be different for states in cities layer, so additional parameter is needed to differentiate between those two.Complete code could then look something like this:
Here is sample screenshot: