1

I have a set of markers each stored in different Layers... lets say:

let earth= {
    layer:{
        ...
        Markers:{...}
    }
}
let mars= {
    layer:{
        ...
        Markers:{...}
    }
}
let pluto= {
    layer:{
        ...
        Markers:{...}
    }
}

I switch to different maps (with individual markers) with this function:

function setMap(selectedMap, htmlElement, ifSub = false) {
    if (currentMap != selectedMap) {
        map.removeLayer(window[currentMap].Layer)
        map.addLayer(window[selectedMap].Layer)

        currentMap = selectedMap
    }
}

With a button (and on launch) I have given some of the markers on pluto a class (lets say "Visited") which changes css for them.

However when I change the map to Earth and back to Pluto the markers from Pluto "forget" that they had a class in the first place. how would I keep the css stored with the marker? And added back to the marker when map.addLayer(...) is called?

3
  • if there is another way to swap around the markers i would love to take a look at that as well
    – Odinh
    Commented Jun 18, 2021 at 11:52
  • There is way too much work to do to just reproduce what you actually have. Have a Minimal, Reproducible Example working in a snippet. Focus more on the reproducible aspect than the minimal ;) Commented Jun 20, 2021 at 19:31
  • 1
    I hate to see people waste their bounties because their questions are hard to understand. "With a button (and on launch) i have given some of the markers on pluto a class (lets say "Visited") which changes css for them." - please show the code for how these classes get added, either on map load or button click. Also please show the code for how the map is being created, and how the markers data is being retrieved and loaded in as markers. Commented Jun 22, 2021 at 17:42

1 Answer 1

3
+50

The problem here is that when a Marker is removed from the map, its icon image is deleted, so any classes or CSS styling you had added manually to it are lost. A new image is created the next time the Marker is added to the map again.

If you just need to make simple changes to the appearance of marker icons, you can create a set of icons with the different images and classes you need, and set the Marker to use the appropriate one. You can set the appropriate initial icon using myMarker = new L.Marker(latlngs, {icon: myIcon}), then change it later with mymarker.setIcon(myOtherIcon). The Marker will remember which Icon it has been set to use, even when it has been removed from the map and added back again. The Leaflet documentation includes a tutorial on using custom icons that shows how to create your own icons. If you want them to have different classes, use the className option when creating them.

Simply using icons with different classes may not work if you need to be able to add and remove classes independently. However, we can extend the definition of a Marker to add class-setting functionality. The following code creates a new class of L.ClassedMarker objects, based on the source code for L.Marker:

L.ClassedMarker = L.Marker.extend({
  options: {
    classes: []
  },
  addClass: function(className) {
    if(this.options.classes.indexOf(className) === -1) {
      this.options.classes.push(className);
    }
    this._initIcon();
  },
  getClasses: function() {
    return this.options.classes;
  },
  removeClass: function(className) {
    var index = this.options.classes.indexOf(className);
    if(index > -1) {
      this.options.classes.splice(index, 1);
    }
    this._initIcon();
  },
  _initIcon: function() {
    L.Marker.prototype._initIcon.apply(this, null);
    for(let cls of this.options.classes) {
      L.DomUtil.addClass(this._icon, cls);
    }
  }
});
L.classedMarker = function(latLng, options) {
  return new L.ClassedMarker(latLng, options);
}

We can use a ClassedMarker in the same way as a normal Marker, but when creating it, we can specify an (optional) list of classes to add to the icon:

var myMarker = L.classedMarker(latlngs, {classes: ["new"]}).addTo(map);

You can also add or remove classes after the ClassedMarker has been created:

myMarker.removeClass("new");
myMarker.addClass("visited");

The ClassedMarker will remember which classes you have added, regardless of whether you add or remove it from the map, or change the marker's icon. You can check what classes have been added using myMarker.getClasses(). Note this only returns your custom classes, not the ones used internally by Leaflet, or set using the className option of the marker's icon.

The code works by maintaining a list of classes in the ClassedMarker's options, rather than in the icon. Each time the icon needs to be updated, it calls the _initIcon() code from the original L.Marker class, but then uses L.DomUtil.addClass() to apply the stored class names to the new icon image.

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