1

I have a map with a bunch of markers and some layer groups based on attributes for those markers. I made layer groups for each attribute and some markers appear in multiple layer groups. When I toggle different layer groups on the live map some markers disappear. I am not a JavaScript expert and did this manually instead of using a loop but here it how I have it set up:


//MY MANY MARKERS

var Lurparken = L.marker([59.3011142,17.9939973], {icon: greenIcon}).bindPopup('Lurparken'),
    Aspuddsparken    = L.marker([59.3075995,17.9944431], {icon: greenIcon}).bindPopup('Aspuddsparken'),
    Sparvagnsparken    = L.marker([59.3298868,18.0031605], {icon: greenIcon}).bindPopup('Spårvagnsparken'),
    Fredhallsparkens    = L.marker([59.3320485,18.0029481], {icon: greenIcon}).bindPopup('Fredhällsparkens plaskdamm'),
    Uggleparken    = L.marker([59.3343715,18.0040208], {icon: greenIcon}).bindPopup('Uggleparken'),
    Observatorielundens    = L.marker([59.3413877,18.056007], {icon: greenIcon}).bindPopup('Observatorielundens Parklek'),
    Kronobergsparken    = L.marker([59.331715,18.0335563], {icon: greenIcon}).bindPopup('Parklek Kronobergsparken'),
    Drakenbergsparken    = L.marker([59.314187,18.038608], {icon: greenIcon}).bindPopup('Drakenbergsparken'),
    Fruktlekparken    = L.marker([59.3109872,18.0221863], {icon: greenIcon}).bindPopup('Fruktlekparken'),
    Junotappan    = L.marker([59.3235004,18.0720134], {icon: greenIcon}).bindPopup('Junotäppan'),
    AndersFranzens    = L.marker([59.311421,18.104492], {icon: greenIcon}).bindPopup('Anders Franzens Park'),
    Kristinebergs    = L.marker([59.334675,18.0063813], {icon: greenIcon}).bindPopup('Kristinebergs Ekparken'),
    Engelskaparkens    = L.marker([59.3377166,18.0012396], {icon: greenIcon}).bindPopup('Engelskaparkens plaskdamm'),
    Vasaparken    = L.marker([59.3399655,18.0419433], {icon: greenIcon}).bindPopup('Vasaparken Lekpark'),
    KungsholmsStrand    = L.marker([59.3358832,18.0406834], {icon: greenIcon}).bindPopup('Lekplatsen Kungsholms Strand'),
    IvarLos    = L.marker([59.3204862,18.0609756], {icon: greenIcon}).bindPopup('Ivar Los Park'),
    Luxparken    = L.marker([59.324224,18.0092568], {icon: redIcon}).bindPopup('Luxparken'),
    Ralis = L.marker([59.3377166,18.0012396], {icon: greenIcon}).bindPopup('Rålis Parklek'),
    Blomsterdalen    = L.marker([59.3078405,18.0261414], {icon: greenIcon}).bindPopup('Lekplats Blomsterdalen'),
    Aventyrsparken    = L.marker([59.304649,18.0355265], {icon: greenIcon}).bindPopup('Äventyrsparken i Årstabergsparken'),
    Sannadalsparken    = L.marker([59.3153587,18.0091349], {icon: greenIcon}).bindPopup('Sannadalsparken'),
    Signalparken    = L.marker([59.3277189,18.0140405], {icon: greenIcon}).bindPopup('Signalparken'),
    Vangavan    = L.marker([59.3219577,17.9926997], {icon: greenIcon}).bindPopup('Vängåvan'),
    LillaBatparken    = L.marker([59.3191497,17.9831104], {icon: greenIcon}).bindPopup('Lilla Båtparken'),
    Arstabergsparken    = L.marker([59.3049749,18.0255049], {icon: greenIcon}).bindPopup('Årstabergsparken'),
    Angbybadet  = L.marker([59.3364975,17.8986038], {icon: blueIcon}).bindPopup('Ängbybadet'),
    Trekantsbadet   = L.marker([59.3126158,18.0106735], {icon: blueIcon}).bindPopup('Trekantsbadet'),
    Solviksbadet    = L.marker([59.3151737,17.9660969], {icon: blueIcon}).bindPopup('Solviksbadet'),
    Malarhojdsbadet = L.marker([59.3001388,17.9254848], {icon: blueIcon}).bindPopup('Mälarhöjdsbadet'),
    TantoSandBeach = L.marker([59.3118604,18.0384076], {icon: blueIcon}).bindPopup('Tanto sand beach'),
    SicklaStrandbad = L.marker([59.301995,18.1246048], {icon: blueIcon}).bindPopup('Sickla strandbad'),
    Reimersholmskajen = L.marker([59.3170847,18.023135], {icon: greenIcon}).bindPopup('Reimersholmskajen​ Lekpark'),
    GustafAdolfsParklek = L.marker([59.3370994,18.0997679], {icon: greenIcon}).bindPopup('Gustaf Adolfs Parklek'),
    Honungslekplatsen = L.marker([59.3454418,18.0925069], {icon: greenIcon}).bindPopup('Honungslekplatsen'),
    LekparkLinnegatan = L.marker([59.3356294,18.0876201], {icon: greenIcon}).bindPopup('Lekpark Linnegatan 74'),
    LekplatsBranneriet = L.marker([59.3174423,18.0171169], {icon: greenIcon}).bindPopup('Lekplats Bränneriet'),
    Hogalid = L.marker([59.3172023,18.0356642], {icon: greenIcon}).bindPopup('Högalid park'),
    Sockerskalen = L.marker([59.3092874,18.048598], {icon: greenIcon}).bindPopup('Sockerskålen lekpark'),
    Vitabergsparkens = L.marker([59.3105286,18.0899339], {icon: greenIcon}).bindPopup('Vitabergsparkens lekplats'),
    Pampasparken    = L.marker([59.3506851,18.0019008], {icon: greenIcon}).bindPopup('Pampasparken'),
    Bergsparken = L.marker([59.3532246,17.9985754], {icon: greenIcon}).bindPopup('Bergsparken'),
    LekplatsNybodagatan = L.marker([59.3561657,17.9906558], {icon: greenIcon}).bindPopup('Lekplats Nybodagatan'),
    Skytteholmsparken = L.marker([59.3588629,17.9929818], {icon: greenIcon}).bindPopup('Skytteholmsparken'),
    Blomparken = L.marker([59.2985831,18.0377624], {icon: greenIcon}).bindPopup('Blomparken'),
    Grynkvarnsparken = L.marker([59.2974055,18.0735674], {icon: greenIcon}).bindPopup('Grynkvarnsparken'),
    Sickla = L.marker([59.3048158,18.108975], {icon: greenIcon}).bindPopup('Sickla park'),
    Dalen = L.marker([59.3061503,18.1535634], {icon: greenIcon}).bindPopup('Dalén park'),
    Motalaparken = L.marker([59.3533865,18.0942552], {icon: greenIcon}).bindPopup('Motalaparken'),
    Dianaparkens = L.marker([59.3563711,18.1012935], {icon: greenIcon}).bindPopup('Dianaparkens Parklek'),
    Ekorrparken = L.marker([59.3559581,18.0852826], {icon: greenIcon}).bindPopup('Ekorrparken Lekplats'),
    Halsingehajden = L.marker([59.3440572,18.04076], {icon: greenIcon}).bindPopup('Lekplatsen Hälsingehöjden'),
    Solvandan = L.marker([59.343872,18.0337046], {icon: greenIcon}).bindPopup('Solvändan'),
    TranebergsbronSkatepark = L.marker([59.3049749,18.0255049], {icon: redIcon}).bindPopup('Tranebergsbron Skatepark'),
    Solvikangens = L.marker([59.3166851,17.9613786], {icon: greenIcon}).bindPopup('Solvikangens Lekplats'),
    SolvikSkatepark= L.marker([59.3166483,17.9618368], {icon: redIcon}).bindPopup('Solvik skatepark Rhino'),
    Vattersdalden = L.marker([59.2964647,18.0595962], {icon: greenIcon}).bindPopup('Vättersdälden'),
    Trollparken = L.marker([59.3003486,18.0618205], {icon: greenIcon}).bindPopup('Trollparken'),
    HumlanSkatepark = L.marker([59.3399548,18.070861], {icon: redIcon}).bindPopup('Humlan skateboard park'),
    SkateparkRhino = L.marker([59.3349077,17.9886289], {icon: redIcon}).bindPopup('Skatepark Rhino'),
    StoraBlecktornsparken = L.marker([59.3069209,18.0866587], {icon: greenIcon}).bindPopup('Stora Blecktornsparken'),
    PrimusSkatepark = L.marker([59.3250964,17.9998018], {icon: redIcon}).bindPopup('Primus Skatepark'),
    RalisSkatepark = L.marker([59.3290717,18.0217644], {icon: redIcon}).bindPopup('Rålis Skatepark'),
    KristinebergsSkatepark = L.marker([59.3370164,18.0037855], {icon: redIcon}).bindPopup('Kristinebergs Skatepark'),
    ParkblekenSkaneglantan = L.marker([59.3112462,18.0702012], {icon: greenIcon}).bindPopup('Parkbleken Skånegläntan'),
    Humlegarden = L.marker([59.3406553,18.0728746], {icon: greenIcon}).bindPopup('Humlegården parklek'),
    Timmermansparken = L.marker([59.3130356,18.0624603], {icon: greenIcon}).bindPopup('Timmermansparken'),
    BjornsTradgard = L.marker([59.31533,18.0740494], {icon: greenIcon}).bindPopup('Björns trädgård'),
    BjornsSkatepark = L.marker([59.3151381,18.074384], {icon: redIcon}).bindPopup('Björns Skatepark'),
    Bryggartappan = L.marker([59.3102588,18.0797964], {icon: greenIcon}).bindPopup('Bryggartäppan'),
    EllenKeysLekplats = L.marker([59.3440353,18.0641552], {icon: greenIcon}).bindPopup('Ellen Keys Lekplats'),
    Pontonjarparkens= L.marker([59.329508,18.0325937], {icon: greenIcon}).bindPopup('Pontonjärparkens lekplats'),
    KungsholmsHamnplan = L.marker([59.3275721,18.0462158], {icon: greenIcon}).bindPopup('Lekplatsen Kungsholms hamnplan'),
    Byparkens = L.marker([59.3524237,17.9842882], {icon: greenIcon}).bindPopup('Byparkens Parklek'),
    TranebergsFritidspark = L.marker([59.3345913,17.9887147], {icon: greenIcon}).bindPopup('Tranebergs Fritidspark'),
    Tessinparken = L.marker([59.3446553,18.0953217], {icon: greenIcon}).bindPopup('Parklek Tessinparken'),
    VanadislundensNedre = L.marker([59.3472582,18.0534746], {icon: greenIcon}).bindPopup('Vanadislundens Nedre Lekplats'),
    VanadislundensOvre = L.marker([59.3493288,18.0541187], {icon: greenIcon}).bindPopup('Vanadislundens Övre Lekplats'),
    Annedalsparken = L.marker([59.363506,17.9476855], {icon: greenIcon}).bindPopup('Annedalsparken'),
    KungsholmensInternationellaBiblioteket = L.marker([59.3049749,18.0255049], {icon: yellowIcon}).bindPopup('Kungsholmens Internationella biblioteket'),
    LillaKvarnholmen = L.marker([59.3153135,18.1378676], {icon: greenIcon}).bindPopup('Lilla Kvarnholmen Lekplats'),
    MulleMecks = L.marker([59.3818079,17.9901311], {icon: greenIcon}).bindPopup('Mulle Mecks Lekpark'),
    Simbaparken = L.marker([59.3049749,18.0255049], {icon: yellowIcon}).bindPopup('Simbaparken'),
    LekBusNacka = L.marker([59.3049749,18.0255049], {icon: yellowIcon}).bindPopup('Lek o Bus i Nacka'),
    MallScandinavia = L.marker([59.3691656,18.005247], {icon: greenIcon}).bindPopup('Westfield Mall of Scandinavia'),
    Langsjoparken = L.marker([59.3049749,18.0255049], {icon: yellowIcon}).bindPopup('ÅrstaberLångsjöparkengsparken');

//THE LAYER GROUPS I MADE BASED ON ATTRIBUTES

    var AllPlaygrounds = L.layerGroup([Sparvagnsparken, Fredhallsparkens, Uggleparken, Observatorielundens, Kronobergsparken, Drakenbergsparken, Fruktlekparken, Junotappan, AndersFranzens, Kristinebergs, Engelskaparkens, Vasaparken, KungsholmsStrand, Luxparken, IvarLos, Ralis, Blomsterdalen, Sannadalsparken, Signalparken, LillaBatparken, Vangavan, Lurparken, Humlegarden, StoraBlecktornsparken, Bryggartappan, VanadislundensOvre, VanadislundensNedre, EllenKeysLekplats, Timmermansparken, ParkblekenSkaneglantan, BjornsTradgard, TranebergsFritidspark, Trollparken, Aspuddsparken, Solvikangens, Vattersdalden]);
    var partialFence = L.layerGroup([Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,Junotappan,AndersFranzens,Kristinebergs,KungsholmsStrand,Blomsterdalen,Sannadalsparken,LillaBatparken,Humlegarden,Timmermansparken,ParkblekenSkaneglantan,BjornsTradgard,TranebergsFritidspark,Aspuddsparken,Vattersdalden]);
    var fence = L.layerGroup([Sparvagnsparken,IvarLos,Luxparken,Signalparken,Vangavan,Bryggartappan,VanadislundensOvre,VanadislundensNedre,Solvikangens]);
    var wc = L.layerGroup([Sparvagnsparken, Fredhallsparkens, Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,Fruktlekparken,Junotappan,Kristinebergs,Engelskaparkens,Vasaparken,Blomsterdalen,Vangavan,Lurparken,Humlegarden,StoraBlecktornsparken,Bryggartappan,VanadislundensNedre,ParkblekenSkaneglantan,BjornsTradgard,Aspuddsparken,Solvikangens,Vattersdalden]);
    var toddler = L.layerGroup([Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,AndersFranzens,Vasaparken,IvarLos,Luxparken,Ralis,Humlegarden,ParkblekenSkaneglantan,TranebergsFritidspark,Aspuddsparken,Vattersdalden]);
    var water = L.layerGroup([Fredhallsparkens,Drakenbergsparken,Engelskaparkens,Luxparken,Ralis,Sannadalsparken,Vangavan,TranebergsFritidspark,Aspuddsparken]);
    var indoor = L.layerGroup([Observatorielundens,Kronobergsparken,Drakenbergsparken,Vasaparken,Ralis,Vangavan,Humlegarden,StoraBlecktornsparken,ParkblekenSkaneglantan,BjornsTradgard,Aspuddsparken,Vattersdalden]);
    var animals = L.layerGroup([StoraBlecktornsparken,Aspuddsparken]);
    var access = L.layerGroup([Humlegarden,BjornsTradgard]);
    var grill = L.layerGroup([Sparvagnsparken,Drakenbergsparken,Junotappan,IvarLos,Ralis,Humlegarden,ParkblekenSkaneglantan,Vattersdalden]);
    var favorite = L.layerGroup([]);

//My MAP STARTS HERE

    var main = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
            attribution: '<a href="https://www.openstreetmap.org/">OpenStreetMap</a>, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, <a href="https://www.mapbox.com/">Mapbox</a>',
                maxZoom: 18,
                id: 'mapbox/streets-v11',
                tileSize: 512,
                zoomOffset: -1,
                zoomControl: false,
                accessToken: 'A MAP KEY'
        });
    var baseMaps = {
        "Lek's Play": main
    };

    var overlayMaps = {
         "All Playgrounds":AllPlaygrounds,
         "Restroom": wc,
         "Public grills": grill,
         "Accessible equipment": access,
         "Indoor area": indoor,
         "Fully fenced": fence,
         "Partially fenced": partialFence,
         "Animals": animals,
         "Water play": water,
         "Toddler Area": toddler
    };

    var map = L.map('mapid', {
             center: [59.3244941,18.028934],
             zoom: 12,
             layers: [main, AllPlaygrounds]
    });


I have the control set up outside the map with a different parent but it is the standard:

var control = L.control.layers(null, overlayMaps,{collapsed:false});
control.addTo(map);

What should I do so that a user can select multiple of the layer groups and not lose pins when toggling?

1 Answer 1

0

Interesting problem, which seems simple at first sight, but doesn't seem to have straightforward solution.

When group layer overlay is added to the map through layer control, actually member layers are added to the map. When another group layer overlay is added, only those member layers are added that are not already on the map. Consequently when group layer is removed from the map, all it's member layers are removed, even if they are also member of another group.

One of possible ways to solve this problem is adding member layers of the group overlay "manually" to the map one by one and checking if they already exist on the map. If member layer already exists, it's custom map membership counter is increased. Reverse process is done when removing group overlay. Couner is decreased for the member and if zero, actually removed.

To achieve this through layer control, dummy nondisplayed layers are introduced, used only to trigger overlayedd and overlayremove events, where actual adding and removing is done.

So code could then look something like this:

  var overlay = [];    
  overlay[0] = [Sparvagnsparken, Fredhallsparkens, Uggleparken, Observatorielundens, Kronobergsparken, Drakenbergsparken, Fruktlekparken, Junotappan, AndersFranzens, Kristinebergs, Engelskaparkens, Vasaparken, KungsholmsStrand, Luxparken, IvarLos, Ralis, Blomsterdalen, Sannadalsparken, Signalparken, LillaBatparken, Vangavan, Lurparken, Humlegarden, StoraBlecktornsparken, Bryggartappan, VanadislundensOvre, VanadislundensNedre, EllenKeysLekplats, Timmermansparken, ParkblekenSkaneglantan, BjornsTradgard, TranebergsFritidspark, Trollparken, Aspuddsparken, Solvikangens, Vattersdalden];
  overlay[1] = [Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,Junotappan,AndersFranzens,Kristinebergs,KungsholmsStrand,Blomsterdalen,Sannadalsparken,LillaBatparken,Humlegarden,Timmermansparken,ParkblekenSkaneglantan,BjornsTradgard,TranebergsFritidspark,Aspuddsparken,Vattersdalden];
  overlay[2] = [Sparvagnsparken,IvarLos,Luxparken,Signalparken,Vangavan,Bryggartappan,VanadislundensOvre,VanadislundensNedre,Solvikangens];
  overlay[3] = [Sparvagnsparken, Fredhallsparkens, Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,Fruktlekparken,Junotappan,Kristinebergs,Engelskaparkens,Vasaparken,Blomsterdalen,Vangavan,Lurparken,Humlegarden,StoraBlecktornsparken,Bryggartappan,VanadislundensNedre,ParkblekenSkaneglantan,BjornsTradgard,Aspuddsparken,Solvikangens,Vattersdalden];
  overlay[4] = [Uggleparken,Observatorielundens,Kronobergsparken,Drakenbergsparken,AndersFranzens,Vasaparken,IvarLos,Luxparken,Ralis,Humlegarden,ParkblekenSkaneglantan,TranebergsFritidspark,Aspuddsparken,Vattersdalden];
  overlay[5] = [Fredhallsparkens,Drakenbergsparken,Engelskaparkens,Luxparken,Ralis,Sannadalsparken,Vangavan,TranebergsFritidspark,Aspuddsparken];
  overlay[6] = [Observatorielundens,Kronobergsparken,Drakenbergsparken,Vasaparken,Ralis,Vangavan,Humlegarden,StoraBlecktornsparken,ParkblekenSkaneglantan,BjornsTradgard,Aspuddsparken,Vattersdalden];
  overlay[7] = [StoraBlecktornsparken,Aspuddsparken];
  overlay[8] = [Humlegarden,BjornsTradgard];
  overlay[9] = [Sparvagnsparken,Drakenbergsparken,Junotappan,IvarLos,Ralis,Humlegarden,ParkblekenSkaneglantan,Vattersdalden];

  var dummy = [];    
  dummy[0] = L.polyline([[0, 0], [0, 0]], {myId: 0, stroke: false, interactive: false});
  dummy[1] = L.polyline([[0, 0], [0, 0]], {myId: 1, stroke: false, interactive: false});
  dummy[2] = L.polyline([[0, 0], [0, 0]], {myId: 2, stroke: false, interactive: false});
  dummy[3] = L.polyline([[0, 0], [0, 0]], {myId: 3, stroke: false, interactive: false});
  dummy[4] = L.polyline([[0, 0], [0, 0]], {myId: 4, stroke: false, interactive: false});
  dummy[5] = L.polyline([[0, 0], [0, 0]], {myId: 5, stroke: false, interactive: false});
  dummy[6] = L.polyline([[0, 0], [0, 0]], {myId: 6, stroke: false, interactive: false});
  dummy[7] = L.polyline([[0, 0], [0, 0]], {myId: 7, stroke: false, interactive: false});
  dummy[8] = L.polyline([[0, 0], [0, 0]], {myId: 8, stroke: false, interactive: false});
  dummy[9] = L.polyline([[0, 0], [0, 0]], {myId: 9, stroke: false, interactive: false});

  var overlayMaps = {
       "All Playgrounds": dummy[0],
       "Restroom": dummy[1],
       "Public grills": dummy[2],
       "Accessible equipment": dummy[3],
       "Indoor area": dummy[4],
       "Fully fenced": dummy[5],
       "Partially fenced": dummy[6],
       "Animals": dummy[7],
       "Water play": dummy[8],
       "Toddler Area": dummy[9]
  };

var map = L.map('map').setView([59.3244941,18.028934], 12);

var tileLayer = L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
  maxZoom: 18,
  attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
    '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
  id: 'mapbox.light'
}).addTo(map);

var baseLayers = {
  'OSM': tileLayer
}

var markers = L.layerGroup([]).addTo(map);

map.on('overlayadd', function(evt) {
  var i = overlayMaps[evt.name].options.myId;
  for (var j = 0; j < overlay[i].length; j++) {
    if (markers.hasLayer(overlay[i][j])) {
      overlay[i][j].myCount += 1;
      }
    else {  
      overlay[i][j].myCount = 1;
      overlay[i][j].addTo(markers);
    }
  }
});

map.on('overlayremove', function(evt) {
  var i = overlayMaps[evt.name].options.myId;
  for (var j = 0; j < overlay[i].length; j++) {
    if (markers.hasLayer(overlay[i][j])) {
      overlay[i][j].myCount -= 1;
      if (overlay[i][j].myCount == 0) {
        markers.removeLayer(overlay[i][j]);
      }
    }
  }
});

L.control.layers(baseLayers, overlayMaps).addTo(map);
2
  • Wow, I will try that! Thank you so much! Commented May 25, 2020 at 21:20
  • This works brilliantly, thank you. My next challenge will be getting my control to act with AND logic. Commented May 26, 2020 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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