1

I followed the “Interactive Choropleth Map” tutorial for leaflet, available here(https://leafletjs.com/examples/choropleth/). Then I put all the things in a function, and I am calling that function on a button click like this

<p><button type="button" onclick="AddLayer((getElementById('level').value),(getElementById('month').value))">Visualize</button></p>

The problem with my code is if I press the button twice all the things appear again on the map (i.e. GeoJson Layer and other elements of map like Legend, Info Class Div (which Shows Info of states on mouse hover)) While the things added earlier on first click also remain there. I tried to use the map.removeLayer() function but it is not working.

Is there any way that if the user clicks the button twice then all the things already added by first click could get removed before adding them again with new parameters?

Code for the BaseMap

//Basemap Layers
var Standard = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
});

//Map layout with baselayer
var map = L.map('mapid', {
    center: [33.394759218577995, -112.98339843750001],
    zoom: 4,
    zoomControl: false,
    layers: [Standard]
});

//Relocating the zoom controls
L.control.zoom({
     position:'topright'
}).addTo(map);

//creating an object for basemap
var baseMaps = {
    "Standard": Standard
};

//creating a layer control and adding basemap to map layout
L.control.layers(baseMaps).addTo(map);


Code of the function to add Choropleth Map


// defining the variable
var geojson;

function AddLayer(level,month){



//Remove Existing Layer which is not working
if(geojson)
{
  map.removeLayer(geojson)
}

//Adding the data depending upon the input
if (level == 'statesData')
{
geojson = L.geoJson(statesData);
geojson.addTo(map);
}

else if (level == 'countiesData')
{
    geojson = L.geoJson(countiesData);
    geojson.addTo(map);   
}

// listeners
//creating a color ramp
function getColor(d) {
    return d > 64 ?  '#800026' :
           d > 32 ?  '#BD0026' :
           d > 16 ?  '#E31A1C' :
           d > 8 ?  '#FC4E2A' :
           d > 4 ?  '#FD8D3C' :
           d > 2 ?  '#FEB24C' :
           d > 1 ?  '#FED976' :
                    '#FFEDA0' ;
}

//function to implement the styling (with if statements for every month
function style(feature) {

    var clr
            if (month == 'Jan_20'){clr =  getColor(feature.properties.Jan_20)}
            else if (month == 'Feb_20'){clr =  getColor(feature.properties.Feb_20)}
            else if (month == 'Mar_20'){clr =  getColor(feature.properties.Mar_20)}

    return {
        fillColor: clr ,
        weight: 2,
        opacity: 1,
        color: 'white',
        dashArray: '3',
        fillOpacity: 0.5
    };
}
L.geoJson(statesData, {style: style}).addTo(map);


//Adding Event Listener for mouse hover
function highlightFeature(e) {
    var layer = e.target;

    layer.setStyle({
        weight: 5,
        color: '#666',
        dashArray: '',
        fillOpacity: 0.7
    });

    if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
        layer.bringToFront();
    }

    info.update(layer.feature.properties);
}

// When mouse goes away reset the style
function resetHighlight(e) {
    geojson.resetStyle(e.target);

    info.update();
}

//define a click listener that zooms to the state
function zoomToFeature(e) {
    map.fitBounds(e.target.getBounds());
}

//For each feature 
function onEachFeature(feature, layer) {
    layer.on({
        mouseover: highlightFeature,
        mouseout: resetHighlight,
        click: zoomToFeature
    });
}

geojson = L.geoJson(statesData, {
    style: style,
    onEachFeature: onEachFeature
}).addTo(map);

//On hover information about the state
var info = L.control();

info.onAdd = function (map) {
    this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
    this.update();
    return this._div;
};

// method to update the control based on feature properties passed
info.update = function (props) {
    if (month == 'Jan_20'){this._div.innerHTML = '<h4>Unemployement</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Jan_20 + ' Percent': 'Hover over a state');}
    else if (month == 'Feb_20') {this._div.innerHTML = '<h4>Unemployement</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Feb_20 + ' Percent': 'Hover over a state');}
    else if (month == 'Mar_20') {this._div.innerHTML = '<h4>Unemployement</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Mar_20 + ' Percent': 'Hover over a state');}
};

info.addTo(map);

//Adding the legend var legend = L.control({position: 'bottomright'});
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {

    var div = L.DomUtil.create('div', 'info legend'),
        grades = [0, 1, 2, 4, 8, 16, 32, 64],
        labels = [];

// loop through our density intervals and generate a label with a colored square for each interval
    for (var i = 0; i < grades.length; i++) {
        div.innerHTML +=
            '<i style="background:' + getColor(grades[i] + 1) + '"></i> ' +
            grades[i] + (grades[i + 1] ? '&ndash;' + grades[i + 1] + '<br>' : '+');
    }

    return div;
};

legend.addTo(map);

}

9
  • Problem is that your geojson variable is local to the AddLayer function and is not preserved from call to call. Just move definition var geojson outside the function. – TomazicM Dec 28 '20 at 13:17
  • I also tried this (defined the var geojson variable outside but even then no success. Anyways Thank you so much for your time. – Hassam Ali Dec 28 '20 at 20:37
  • It's hard what goes wrong with your code without trying it. If you put working example on JSFiddle or Plunker, I can check it. – TomazicM Dec 29 '20 at 10:16
  • My geojson files are very large thats whay I am send this link. complete project is available here https://drive.google.com/drive/folders/1MjjH-gZauL1zF1zOFNmK0OxUguGlfJzT?usp=sharing – Hassam Ali Dec 29 '20 at 16:16
  • And thank you so much once again – Hassam Ali Dec 29 '20 at 16:17
2

The main thing that is wrong in your code is that in the function AddLayer, where you define new GeoJSON layer for newly selected month, GeoJSON layer is defined and added to the map three times.

You also define and add to the map info and legend controls inside AddLayer function, so new controls are added to the map at each change of the data.

In the code below all of the auxiliary functions were moved outside the AddLayer function. Since some of them need month variable value, global variable was created. New variable firstTime is used to add info control once after first load of the data. Surplus definitions of GeoJSON layer were commented out.

var firstTime = true;
var month;

function style(feature) {
  var clr;
  if (month == 'Jan_20'){clr =  getColor(feature.properties.Jan_20)}
  else if (month == 'Feb_20'){clr =  getColor(feature.properties.Feb_20)}
  else if (month == 'Mar_20'){clr =  getColor(feature.properties.Mar_20)}
  else if (month == 'Apr_20'){clr =  getColor(feature.properties.Apr_20)}
  else if (month == 'May_20'){clr =  getColor(feature.properties.May_20)}
  else if (month == 'Jun_20'){clr =  getColor(feature.properties.Jun_20)}
  else if (month == 'Jul_20'){clr =  getColor(feature.properties.Jul_20)}
  else if (month == 'Aug_20'){clr =  getColor(feature.properties.Aug_20)}
  else if (month == 'Sep_20'){clr =  getColor(feature.properties.Sep_20)}
  else if (month == 'Oct_20'){clr =  getColor(feature.properties.F20_Oct)}
  else if (month == 'Nov_20'){clr =  getColor(feature.properties.F20_Nov)}

  return {
    fillColor: clr ,
    weight: 2,
    opacity: 1,
    color: 'white',
    dashArray: '3',
    fillOpacity: 0.5
  };
}

function getColor(d) {
  return d > 32 ?  '#bd0026' :
         d > 16 ?  '#f03b20' :
         d > 8 ?  '#fd8d3c' :
         // d > 16 ?  '#FC4E2A' :
         d > 4 ?  '#fecc5c' :
         // d > 4 ?  '#FEB24C' :
         d > 2 ?  '#ffeda0' :
                  '#ffffb2' ;
}

function highlightFeature(e) {
  var layer = e.target;
  layer.setStyle({
    weight: 5,
    color: '#666',
    dashArray: '',
    fillOpacity: 0.7
  });
  if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
    layer.bringToFront();
  }
  info.update(layer.feature.properties);
}

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
  });
}

var info = L.control();

info.onAdd = function (map) {
  this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
  this.update();
  return this._div;
};

info.update = function (props) {
  if (month == 'Jan_20'){this._div.innerHTML = '<h4>Unemployement Jan 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Jan_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Feb_20') {this._div.innerHTML = '<h4>Unemployement Feb 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Feb_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Mar_20') {this._div.innerHTML = '<h4>Unemployement Mar 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Mar_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Apr_20') {this._div.innerHTML = '<h4>Unemployement Apr 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Apr_20 + ' Percent': 'Hover over a state');}
  else if (month == 'May_20') {this._div.innerHTML = '<h4>Unemployement May 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.May_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Jun_20') {this._div.innerHTML = '<h4>Unemployement Jun 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Jun_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Jul_20') {this._div.innerHTML = '<h4>Unemployement Jul 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Jul_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Aug_20') {this._div.innerHTML = '<h4>Unemployement Aug 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Aug_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Sep_20') {this._div.innerHTML = '<h4>Unemployement Sep 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.Sep_20 + ' Percent': 'Hover over a state');}
  else if (month == 'Oct_20') {this._div.innerHTML = '<h4>Unemployement Oct 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.F20_Oct + ' Percent': 'Hover over a state');}
  else if (month == 'Nov_20') {this._div.innerHTML = '<h4>Unemployement Nov 20</h4>' +  (props ?'<b>' + props.NAME + '</b><br />' + props.F20_Nov + ' Percent': 'Hover over a state');}
};

var legend = L.control({position: 'bottomright'});

legend.onAdd = function (map) {
  var div = L.DomUtil.create('div', 'info legend'),
    grades = [0, 2, 4, 8, 16, 32],
    labels = [];

  for (var i = 0; i < grades.length; i++) {
    div.innerHTML +=
      '<i style="background:' + getColor(grades[i] + 1) + '"></i> ' +
      grades[i] + (grades[i + 1] ? '&ndash;' + grades[i + 1] + '<br>' : '+');
  }
  return div;
};

legend.addTo(map);

function AddLayer(selMonth){
  month = selMonth;
  if(geojson) {
    map.removeLayer(geojson)
  }

/*
  geojson = L.geoJson(statesData);
  geojson.addTo(map);

  L.geoJson(statesData, {style: style}).addTo(map);
*/

  geojson = L.geoJson(statesData, {
    style: style,
    onEachFeature: onEachFeature
  }).addTo(map);
  
  if (firstTime) {
    firstTime = false;
    info.addTo(map);
  }
  info.update();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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