2

I want to get label of the layer selected in option control in order to know which thematic analysis to run. because I have just one layer, but different fillcolor regarding the label in the list control.

I want to have two separate overlays coming from the same GeoJSON source: one for population data and the other for job data? And then in the layers control select one or the other.

var mymap = L.map('mapid').setView([35.402484, 8.125763], 13);          
var OpenStreetMap_Mapnik = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(mymap);
/Color class for Population
var populationtClass = [
[0, 'rgb(249, 253, 255)'],
[500, 'rgb(195, 225, 243)'],
[1000, 'rgb(180, 219, 243)'],
[2000, 'rgb(124, 188, 227)'],
[5000, 'rgb(89, 160, 203)'],
[9000, 'rgb(30, 123, 180)'],
[19800, 'rgb(8,  86, 133)']
 ];
 //Color Class for Job
 var JobClass = [
[0, 'rgb(255, 255, 255)'],
[20, 'rgb(243, 250, 213)'],
[300, 'rgb(241, 252, 197)'],
[800, 'rgb(234, 252, 164)'],
[1000, 'rgb(224, 247, 132)'],
[2000, 'rgb(214, 250, 68)'],
[3000, 'rgb(180,222,15)']
 ];
 //function Returning the Color
 var coloring = function (thresholds, value) {
                for (var i = 0; i < thresholds.length - 1; i++) {
                    if (value < thresholds[i + 1][0])
                        return thresholds[i][1];
                }
                return thresholds[thresholds.length - 1][1];
};

//Loading Geojson of Zone1 and color it by population value or job value
var Zone1=new L.geoJson(Zone1,{
      style: function (feature) {
              var population = feature.properties.Pop_2015;
              var work = feature.properties.job_2015;
                                return {

                                    //HERE THE STUFF++++++++++++++++++++++++++++++++++++++++++++

                                    if(layer.label="Population"){
            //IF LABEL OF THE LAYER IS POP RUN POP THEMATIC COLOR
                 fillColor: coloring(populationtClass, population),
                 else if (layer.label="Jobs"){
                 //IF LABEL OF THE LAYER IS JOB RUN JOB THEMATIC COLOR
                    fillColor: coloring(JobClass, work),
                 }
                 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                        fillOpacity: 0.75,
                        weight: 1,
                        color: 'black'
                    };
                },
onEachFeature: function (feature, layer) {
        layer.on({
                        'mousemove': function (e) {
                            e.target.setStyle({
                                weight: 7,
                                color: 'red'

                            });

                          },
                        'mouseout': function (e) {
                            Zone1.resetStyle(e.target);


                        },
                        'click': function (e) {
                            mymap.fitBounds(e.target.getBounds());

                        }});}});

L.control.layers({
'BaseMap' :OpenStreetMap_Mapnik
    },{
'Population':Zone1,
'Jobs':Zone1
}).addTo(mymap);
  • If I understand correctly from the code, you want to have two separate overlays coming from the same GeoJSON source: one for population data and the other for job data? And then in the layers control select one or the other? – TomazicM Jan 26 at 11:51
  • Exactly, I couldn't do it ! – Rabie Ben Jan 26 at 11:53
2

The way you figured it out, it is not possible. If you have the same overlay twice in Leaflet layer control, Leaflet does not distinguish between those two layers despite having different labels.

There are several possible solutions to achieve what you want. One is to have two separate overlays, each with it's own style, but I know from your past questions you don't want this.

Another possibility is to create your own selection control and upon selecting specific overlay use setStyle method with desired style. This of course requires quite some work.

Yet another very hacky possibility is to create two dummy layers (not shown on map) to be used in layer control just for switching between two different styles for GeoJSON layer. Those two layers are added to the layer control and then listeners are set up for overlayadd and overlayremove events, where the required style is set to GeoJSON layer.

function stylePopulation(feature) {
  var population = feature.properties.Pop_2015;
  return {
    fillColor: coloring(populationtClass, population),
    fillOpacity: 0.75,
    weight: 1,
    color: 'black'
  };
}

function styleJob(feature) {
  var work = feature.properties.job_2015;
  return {
    fillColor: coloring(JobClass, work),
    fillOpacity: 0.75,
    weight: 1,
    color: 'black'
  };
}

var layerZone1 = new L.geoJson(Zone1, {
  onEachFeature: function (feature, layer) {
    layer.on({
      'mousemove': function (e) {
        e.target.setStyle({
          weight: 7,
          color: 'red'
        });
      },
      'mouseout': function (e) {
        layerZone1.resetStyle(e.target);
      },
      'click': function (e) {
        mymap.fitBounds(e.target.getBounds());
      }
    });
  }
});

var dummy1 = L.polyline([[0, 0], [0, 0]], {stroke: false, interactive: false});
var dummy2 = L.polyline([[0, 0], [0, 0]], {stroke: false, interactive: false});

L.control.layers(
  {
    'BaseMap': OpenStreetMap_Mapnik
  },
  {
    'Population': dummy1,
    'Jobs': dummy2
  }
).addTo(mymap);

function removeOverlay(overlay) {
  map.removeLayer(overlay);
}

var removeInProgress = false;

map.on('overlayadd', function(evt) {
  if (evt.name == 'Population') {
    layerZone1.setStyle(stylePopulation);
    if (!map.hasLayer(layerZone1)) layerZone1.addTo(map);
    if (map.hasLayer(dummy2)) {
      removeInProgress = true;
      setTimeout(removeOverlay, 10, dummy2);
    }
    }
  else if (evt.name == 'Jobs') {
    layerZone1.setStyle(styleJob);
    if (!map.hasLayer(layerZone1)) layerZone1.addTo(map);
    if (map.hasLayer(dummy1)) {
      removeInProgress = true;
      setTimeout(removeOverlay, 10, dummy1);
    }
  }
});

map.on('overlayremove', function(evt) {
  if (removeInProgress) {
    removeInProgress = false;
    return;
  }
  setTimeout(removeOverlay, 10, layerZone1);
});

Logic of switching between overlays is that only one is shown at the same time. If one is selected, the other is deselected (hidden).

Removing of overlay inside event function has to be done over setTimeout function, otherwise it does not work correctly.

Also removing overlay within overlayremove event function requires flag to be set to distinguish between removing dummy overlay or real GeoJSON overlay.

| improve this answer | |

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.