You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Leaflet与Leaflet Routing Machine的撤销/重做功能实现求助

完善Leaflet Routing Machine的撤销/重做功能

咱们先梳理下核心思路:要实现完整的撤销/重做,光靠一个activityBuffer是不够的,得再加一个缓冲区存被撤销的操作(方便重做);另外你用到的undoFlag用来区分「正常操作」和「撤销/重做触发的状态恢复」,这个思路很对,避免把恢复的状态重复存入历史。接下来我帮你补全代码并优化细节:

1. 完善变量定义

首先补充重做缓冲区,同时初始化时要把初始路点存入历史,避免第一次撤销出错:

// 历史操作缓冲区:存每次变更后的路点状态
var activityBuffer = [];
// 重做缓冲区:存被撤销的操作,方便恢复
var redoBuffer = [];
// 标记是否是撤销/重做触发的状态变更,避免重复存入历史
var undoFlag = false;

// 初始化:把初始路点存入历史缓冲区
activityBuffer.push(Routing.getWaypoints());

2. 优化routeselected事件监听

当用户正常修改路点时,清空重做缓冲区(因为新操作后之前的撤销状态不能再重做了);如果是撤销/重做触发的状态变更,就跳过存入历史:

Routing.on('routeselected', function(){
  if (undoFlag) {
    undoFlag = false;
  } else {
    var newWaypoints = Routing.getWaypoints();
    activityBuffer.push(newWaypoints);
    // 新操作后清空重做缓冲区
    redoBuffer = [];
    console.log("历史状态:", activityBuffer);
  }
});

3. 补全undoActivity函数

撤销时,把当前状态移到重做缓冲区,然后恢复上一个历史状态:

function undoActivity(){
  // 至少要有2个状态(初始+至少一次操作)才能撤销
  if (activityBuffer.length > 1) {
    // 把当前状态移到重做缓冲区
    var currentState = activityBuffer.pop();
    redoBuffer.push(currentState);
    // 恢复上一个历史状态
    var oldState = activityBuffer[activityBuffer.length - 1];
    Routing.setWaypoints(oldState);
    // 标记这次状态变更是撤销触发的,避免存入历史
    undoFlag = true;
    console.log("已撤销,当前历史状态数:", activityBuffer.length);
  } else {
    console.log("没有可撤销的操作");
  }
}

4. 添加redoActivity函数

重做时,把重做缓冲区的最后一个状态移回历史缓冲区,然后恢复该状态:

function redoActivity(){
  if (redoBuffer.length > 0) {
    // 把重做缓冲区的最后一个状态移回历史
    var redoState = redoBuffer.pop();
    activityBuffer.push(redoState);
    // 恢复该状态
    Routing.setWaypoints(redoState);
    // 标记这次状态变更是重做触发的,避免存入历史
    undoFlag = true;
    console.log("已重做,当前重做缓冲区剩余:", redoBuffer.length);
  } else {
    console.log("没有可重做的操作");
  }
}

关键细节说明

  • 双缓冲区设计:activityBuffer记录所有正向操作的状态,redoBuffer记录被撤销的操作,这样在用户执行新操作前,都可以重做之前的撤销动作;一旦有新操作,redoBuffer就清空,符合常规的撤销/重做逻辑。
  • undoFlag的作用:因为调用Routing.setWaypoints()会触发routeselected事件,用这个标记可以区分是用户主动修改还是代码恢复状态,避免把恢复的状态重复存入历史缓冲区。
  • 初始状态存入:页面加载时把初始路点存入activityBuffer,保证第一次撤销有状态可恢复。

你可以把这些代码整合到你的项目里,然后给撤销/重做按钮绑定对应的函数(比如onclick="undoActivity()"和onclick="redoActivity()")就可以正常使用啦。

内容的提问来源于stack exchange,提问作者Farhan Habib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:16:20