2
votes

I have a map that shows various geoJson layers of public transit routes in Auckland, NZ. I have added some buttons to the page, independent from the leaflet map, and I only want to have one selected, or to remove the previous geoJson layer when a different button is clicked

I have tried various solutions, so far I have this working:

HTML: 
<button class='btn' id="busButton">Bus Services</button>
<button class='btn' id="cycleButton">Cycle Lanes</button>
<button class='btn' id="ferryButton">Ferry Routes</button>
Script: 
    $("#busButton").click(function(event) {
        event.preventDefault();
        if(map.hasLayer(busRoutesLayer)) {
            $(this).removeClass('selected');
            map.removeLayer(busRoutesLayer);
        } else {
            map.addLayer(busRoutesLayer);
            $(this).addClass('selected');
        }
    });

    $("#cycleButton").click(function(event) {
        event.preventDefault();
        if(map.hasLayer(cycleRouteLayer)) {
            $(this).removeClass('selected');
            map.removeLayer(cycleRouteLayer);
        } else {
            map.addLayer(cycleRouteLayer);
            $(this).addClass('selected');
        }
    });

So far this lets me select multiple layers, but I do not know how to set up a function to remove a layer when one is already on the map, or make the other buttons unclickable until the layer is turned off. Any help appreciated.

1

1 Answers

1
votes

You would like to implement an exclusive selection of your Leaflet Layers, similarly to what Leaflet Layers Control basemaps work, but with external HTML buttons.

A very easy solution is to blindly remove all these Layers from the map and to add back the one associated with the clicked button. So that whichever Layer was there gives place to the new one. Leaflet will not blow up when you try removing what is not there.

That is exactly the same usual solution as for exclusive class toggling for your buttons: you can blindly remove the "selected" class from all your buttons, then add it back to the newly clicked one.

As to easily remove all your Layers from the map, you can use an intermediary Layer Group that you add to the map instead of your Layers. Then add your Layer(s) to that Group instead of directly to the map. Then when you want to remove everything, you can simply use clearLayers on the Group:

var map = L.map('map').setView([48.86, 2.35], 11);

var all = L.layerGroup().addTo(map)
var layer1 = L.circleMarker([48.86, 2.3]);
var layer2 = L.circleMarker([48.86, 2.4]);

$('button').click(function() {
  all.clearLayers();
  $('button').removeClass('selected');

  $(this).data('layer').addTo(all);
  $(this).addClass('selected');
});

$('#layer1btn').data('layer', layer1);
$('#layer2btn').data('layer', layer2);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}

#map {
  height: calc(100% - 35px);
}

.selected {
  color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-GBlVVqOnLycKN+z49gDABUY6RxEQjOw/GHFbpboxpTxAPJQ78C6pAjT08S/1fT9pWOy9PeyDqipC7cBwrfX2cA==" crossorigin=""></script>

<div id="map"></div>

<button id="layer1btn">Layer 1</button>
<button id="layer2btn">Layer 2</button>