0

When you make a Leaflet LayerControl you first make an array of markers, then pass the array to the LayerControl constructor and add the LayerControl to the map, like this:

myLayerGroup = L.layerGroup(arMarker).addTo(map);

However, I want the markers in the Layer Group to change when the user pans the map. I have coded the appropriate event handler, like this:

map.on('dragend',this.onDragEnd);

I then pass the new extent of the map to the server side via Ajax, query the database and get back the markers that are within the new extent.

What I want to do next is add the new markers and delete the old markers that are not within the new extent. But in order to do that I have to access the array that I passed to the LayerControl. I don't want to just delete all the current markers and add the new markers because many of the new markers will also be the current markers.

Is there a way to access that array within the LayerControl, or do I just have to delete the LayerControl and start again?

1

But in order to do that I have to access the array that I passed to the LayerControl.

No, you don't. Just use the addOverlay and removeLayer methods of L.Control.Layer. Keep an external reference to the layers added to the control if you need.

1

The methods L.layerGroup.addLayer() and L.layerGroup.removeLayer() allow you to add and remove markers. The names of these methods was confusing to me because you are not adding or removing a layer, but rather markers in a layer.

That aside, the removeLayer() does not work too well when you want to dynamically remove markers from the layer control because you can’t find the marker in the control. Leaflet does add an id to each marker, but it is done internally and you don’t know what that id is.

I solved this problem by adding my own id in the options of the marker creation line, like this:

marker = L.marker([y,x],{icon:crowRed14Icon,myId:id}).bindPopup(content);

myId:id refers to the id of the record in my MySQL table that represents the marker.

Now when I want to find the markers in the layer control, I loop through them and find myId, like this:

for(key in lyrCrowTrax._layers)
        {
            myId = lyrCrowTrax._layers[key].options["myId"];

If the marker exists in the new markers that come from the Ajax lookup, I leave it in the layer control. If it is not in the new markers it means that the user has panned or zoomed the map away from the marker, and I remove the marker from the layer control, like this:

markerToRemove = lyrCrowTrax._layers[key];
                    // Use the API as it does other things to remove the marker from the map
                    lyrCrowTrax.removeLayer(markerToRemove);

I hope that the leaflet team will add a public method to access a marker in the layer control by an id field. Then I wouldn't have to write code that accesses the internal code of leaflet.js, which may change at some point and break my code.

The whole code, starting from the success callback function of the ajax lookup, is below, and you can see the whole web map application at http://giscourses.net/crowtrax/crowtrax.html.

function updateMarkersSuccess(data)
    {
        var objNewMarker={}; // container for the new markers
        var arMarker = []; // only used the first time to initialize lyrCrowTrax
        for(key in data)
        {
            var id = data[key].id;
            var x = data[key].x;
            var y = data[key].y;
            var aggressiveness = data[key].aggressiveness;
            var description = data[key].description;
            var date_entered = data[key].date_entered;
            content = "<b>Aggressiveness</b>: " + aggressiveness + "<br>" +
                      "<b>What happened</b>: " + description + "<br>" +
                      "<b>Date</b>: " + date_entered;
            numberPoints++;
            if (isNaN(x) || isNaN(y)) 
            {
                continue;
            }
            var dictXY = {lat: y, lng:x, count: 1};
            arHeatmapPoint.push(dictXY);
            //$("#debug").append("x: " + x + ", y: "+ y + "<br>");
            marker = L.marker([y,x],{icon:crowRed14Icon,myId:id}).bindPopup(content);
            //Put all of the new markers into an object with the database id as a key;;
            objNewMarker[id] = marker;
            arMarker.push(marker);              
        }// end for
        // Test if lyrCrowTrax is null and do this only one time
        if(lyrCrowTrax == null)
        {
            lyrCrowTrax = L.layerGroup(arMarker).addTo(map);
            return;
        }
        // Now loop through lyrCrowTrax and extract the database ids
        for(key in lyrCrowTrax._layers)
        {
            myId = lyrCrowTrax._layers[key].options["myId"];
            // Test if this id is also the key in objNewMarker
            // If it is, delete it from objNewMarker
            // If it is not, delete it from lyrCrowTrax
            if(myId in objNewMarker)
            {
                delete objNewMarker[myId];// No API call here, just delete the marker
            }
            else
            {
                    markerToRemove = lyrCrowTrax._layers[key];
                    // Use the API as it does other things to remove the marker from the map
                    lyrCrowTrax.removeLayer(markerToRemove);
            }       
        }
        // Now add the remaining markers in objNewMarker to lyrCrowTrax
        for (myId in objNewMarker)
        {
            lyrCrowTrax.addLayer(objNewMarker[myId]);
        }
    }// end updateMarkersSuccess
1
function onUserPan{
 getNewMarkers(usingNewBoundingBox);
 arMarker.clearLayers();
 map.addLayer(arMarker);
}

map.on("moveend", () => {
 onUserPan();
});

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.