Search code examples
javascriptleafletleaflet.drawleaflet-routing-machine

Undo/Redo for leafet routing machine


I am trying to implement simple undo/redo function for my tool which uses leaflet and leaflet routing machine. Here is my function:

var activityBuffer = [];
var undoFlag = false;

Routing.on('routeselected', function(){
  if (undoFlag) {
     undoFlag = false;
  }
  else {
    var newWaypoints = Routing.getWaypoints();
    activityBuffer.push(newWaypoints);
    console.log(activityBuffer);
  }
});

function undoActivity(){
  var lastStateIndex = activityBuffer.length - 2
     if (lastStateIndex >= 0) {
        var oldState = activityBuffer[lastStateIndex];
        Routing.setWaypoints(oldState);
        activityBuffer.splice( activityBuffer.length -  1, 1);
        undoFlag = true;
        console.log(activityBuffer);
     }
}

It works fine if i just add more points and the routeselected event is fired, but problem is when i move my waypoints and the cordinates of same points are changed, the entry in the activityBuffer of that waypoint is also updated on its own, add another array of new waypoints is also pushed. why so?

For example: enter image description here

enter image description here

I hope i explained my problem. Looking for some help!


Solution

  • I think the problem is that Leaflet Routing Machine under some circumstances mutate (change) the existing waypoint instances in place, rather than always creating new waypoint instances. For example, when dragging a waypoint, the coordinate of the waypoint is overwritten in the same instance.

    Since your activityBuffer saves the references to existing waypoints, those waypoints will also be updated when LRM updates them. Storing copies of the waypoints instead should fix your problem.

    Also note that strictly, you should store the waypoints from the route that is passed to your event handler (routeselected) instead of grabbing the control's waypoints - this might be important when network latency is high, for example.