variable width overlays unable to be removed with one click on layer control dialog

Viewed 60

I'm trying to make it so that the width of the overlay line changes depending on which layer is in use. To wit I have this code:

var params = {
    color: 'blue',
    opacity: 0.75,
    smoothFactor: 1
};

var latlngs = [[30.267222, -97.743056],[31.267222, -96.743056]];

tempParams = Object.assign(params, {weight: 10});
satelliteLines.addLayer(L.polyline(latlngs, tempParams));
tempParams = Object.assign(params, {weight: 3});
lightLines.addLayer(L.polyline(latlngs, tempParams));
tempParams = Object.assign(params, {weight: 5});
streetsLines.addLayer(L.polyline(latlngs, tempParams));

var hasOverlay = false;

mymap.on('baselayerchange', function(e) {
    switch (e.name) {
        case 'Light':
            if (hasOverlay) {
                lightLines.addTo(mymap);
                streetsLines.removeFrom(mymap);
                satelliteLines.removeFrom(mymap);
            }
            break;
        case 'Streets':
            if (hasOverlay) {
                lightLines.removeFrom(mymap);
                streetsLines.addTo(mymap);
                satelliteLines.removeFrom(mymap);
            }
            break;
        case 'Satellite':
            if (hasOverlay) {
                lightLines.removeFrom(mymap);
                streetsLines.removeFrom(mymap);
                satelliteLines.addTo(mymap);
            }
    }
});

mymap.on('overlayadd', function(e) {
    console.log('overlayadd called');
    hasOverlay = true;
});

This works great for when I turn the "Demo" overlay on but it doesn't work so well when I turn the overlay off and I'm in a layer other than the default "Light" layer. What happens, when I'm in a Layer other than the "Light" layer is that the line doesn't get removed. It only gets removed in the "Light" layer.

To overcome that problem I added this:

mymap.on('overlayremove', function(e) {
    console.log('overlayremove called');
    lightLines.removeFrom(mymap);
    streetsLines.removeFrom(mymap);
    satelliteLines.removeFrom(mymap);
});

That's when things start to get strange. In order to remove all this "Demo" overlayer line for any layer other than the default "Light" layer I now have to double click the "Demo" overlay link in the overlay control dialog for the "Demo" overlay line to disappear. I want it to disappear after just one click (which is how it'd normally work anyway if I wasn't trying to adjust the width dynamically).

Per the console.log's I see that the first time I change layers overlayremove is called but overlayadd isn't. This suggests to me that lightLines.removeFrom(mymap); is triggering the overlayremove event. But if that's the case why isn't the overlayadd event being called? Regardless, if I uncheck and then check the "Demo" overlay link in the top right nothing happens. At least not the first time I click it. The line is stillthere and neither overlayadd or overlayremove are called. BUT when I click the "Demo" overlay link overlayadd is called. When I uncheck it after that the line disappears, with overlayremove finally being called.

Anyway, I don't understand this behavior.

Any ideas?

I just want to make it so that the variable width overlay line goes away, no matter what layer is being displayed, after the overlay entry in the menu has been unchecked.

Here's a standalone demo:

https://terrafrost.com/leaflet/demo01.html

1 Answers

L.Control.Layers in your code is only taken care of lightLines

var overlays = {
    'Demo': lightLines
};
L.control.layers(baseMaps, overlays).addTo(mymap);

When you click on the control no satelliteLines neither streetsLines is handled by the control. Also you are never puting hasOverlay to false when the overlay is removed.

So depending on the set of user actions you are doing, different behaviours will happen. As example:

  1. Open the map, Light is default, Demo is off
  2. Demo is clicked (hasOverlay = true and lightLines is added
  3. Click on Streets. lightLines is removed (still in the control is check), streetsLine is added, hasOverlay is true.
  4. Click on Demo. Not event is raised, as lightLines is not on the map, and streetLine is still on the map because the control does not know about it
  5. Click on Demo. lightLines is added to the map
  6. Click on Demo. lightDemo is removed from the map and the overlayremove remove event is raised, so the three overlays layers are removed.

To fix it, I will go for a different approach than yours. Instead of having three different overlay layers use just one. Listen only for baselayerchange events. Do not handled manually in this callback adding or removing the overlay from the map. Just change it style with setStyle.

Related