【问题标题】:How to undo and redo event in Javascript with browser compatible?如何在兼容浏览器的 Javascript 中撤消和重做事件?
【发布时间】:2016-10-06 11:30:02
【问题描述】:

我有一个 T 恤定制设计软件工具,必须为可拖动的文本添加重做和撤消事件

http://wordpress.tshirtecommerce.com/design-online/?product_id=17

我已尝试使用撤消管理器插件http://mattjmattj.github.io/simple-undo/

【问题讨论】:

  • 在 javascript 中做一个 Undo / Redu 系统非常简单,因为函数闭包,你只需要一个数组来存储你的 undo-redo 堆栈,然后将你的 do 和 undo 推送到数组中.例如。 undoredu.push({do:somedofunc(), undo:somundofunc()});我最近在这里使用这种技术制作了一个编辑动画 -> stackoverflow.com/questions/39885261/… 如果你看到了,如果有任何困惑,请告诉我们。
  • 你能告诉我怎么做吗
  • 我看看能不能举个简单的例子..

标签: javascript jquery


【解决方案1】:

我们到了..

这是一个做撤消和重做缓冲区的简单示例,并使用函数闭包来处理重做..

这当然是一个非常简单的例子,所以希望它也很容易遵循,但是没有理由不能使用这种技术来撤消/重做任何事情。任何东西,你传递给闭包的函数都可以被捕获,然后进行回放。

var e = {}; //lets store references to the dom elemements
Array.prototype.slice.call(document.querySelectorAll("[id]")).
  forEach(function (el) { e[el.id] = el; });

var stack = [],
    stackPos = 0,
    names = [];

function showNames() {
  e.lbNames.textContent = names.join(', ');
  e.btUndo.disabled =  stackPos <= 0;
  e.btRedo.disabled = stackPos >= stack.length;
  e.lbBuffer.textContent = stack.length;
}

btAdd.onclick = function () {
  if (!ipName.value) return alert("Please enter some text");
  //a function closure to capture the name
  function add(name) {
    return function () {
      e.ipName.value = '';
      e.ipName.focus();
      names.push(name);
      stackPos ++;
      showNames();
    }
  }
  //no need for closure here, as were just going to pop the
  //last one of the names, and shift the undo-pos back
  function undo() {
    stackPos --;
    names.pop(); 
    showNames();
  }
  //now lets add our do & undo proc
  var doadd = add(ipName.value);
  stack.splice(stackPos);
  stack.push({
    do: doadd,
    undo: undo
  });
  //lets now do our inital do
  doadd();
};

btUndo.onclick = function () {
  var p = stack[stackPos - 1];
  p.undo();
};

btRedo.onclick = function () {
  var p = stack[stackPos];
  p.do();
};

showNames();
<form onsubmit="return false">
  name: <input id="ipName">
  <br><br>
  <button type="submit" id="btAdd" >Add</button>
  <button id="btUndo">Undo</button>
  <button id="btRedo">Redo</button>
  Buffer = <span id="lbBuffer"></span>
  <pre id="lbNames"></pre>
</form>

【讨论】:

    【解决方案2】:

    好的,我原来的帖子让我感到烦恼的一件事是可重用性。撤消/重做也与实现细节联系得太紧密了。

    所以我创建了一个可重用的类版本,同时也添加了一个清晰的选项。

    我认为保留原件比较方便。这样人们就可以查看代码并进行比较。

    var e = {}; //lets store references to the dom elemements
    Array.prototype.slice.call(document.querySelectorAll("[id]")).
      forEach(function (el) { e[el.id] = el; });
    
    
    function UndoRedo(update_callback, clear_callback) {
      this.update_callback = update_callback;
      this.clear_callback = clear_callback;
      this.clear();
    }
    
    UndoRedo.prototype = {
      
      clear: function () {
        this.stack = [];
        this.stackPos = 0;  
        if (this.clear_callback) this.clear_callback();
        this.update();
      },
      
      update: function () {
        if (this.update_callback) this.update_callback();
      },
      
      canUndo: function () { 
        return this.stackPos > 0; 
      },
    
      canRedo: function () {
        return this.stackPos < this.stack.length;
      },
    
      doAction: function (doProc, undoProc) {
        this.stack.splice(this.stackPos);
        this.stack.push({
          do: doProc,
          undo: undoProc
        });
        this.stackPos ++;
        doProc(); 
        this.update();
      },
      
      undo: function () {
        var p = this.stack[this.stackPos - 1];
        this.stackPos --;
        p.undo();
        this.update();
      },
      
      redo: function () {
        var p = this.stack[this.stackPos];
        this.stackPos ++;
        p.do();    
        this.update();
      }
      
    };  
    
    
    
    var     
        names = [],
        undoRedo = new UndoRedo(
          function update() {
            e.lbNames.textContent = names.join(', ');
            e.btUndo.disabled = !this.canUndo();
            e.btRedo.disabled = !this.canRedo();
            e.lbBuffer.textContent = this.stack.length;
          },
          function cleared() {
            names = [];
          }
        );
    
    btAdd.onclick = function () {
      if (!ipName.value) return alert("Please enter some text");
      
      undoRedo.doAction(
        
        function add(name) {
          return function () {
            e.ipName.value = '';
            e.ipName.focus();
            names.push(name);
          }
        }(ipName.value), 
        
        function undo() {
          names.pop(); 
        }
        
      );  
    };
    
    btUndo.onclick = function () {
      undoRedo.undo();
    };
    
    btRedo.onclick = function () {
      undoRedo.redo();
    };
    
    btClear.onclick = function () {
      undoRedo.clear();
    }
    <form onsubmit="return false">
      name: <input id="ipName">
      <br><br>
      <button type="submit" id="btAdd" >Add</button>
      <button id="btUndo">Undo</button>
      <button id="btRedo">Redo</button>
      Buffer = <span id="lbBuffer"></span>
      <button id="btClear">Clear</button>
      <pre id="lbNames"></pre>
    </form>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-09
      • 2018-01-17
      • 1970-01-01
      • 2012-10-19
      • 2011-05-11
      • 1970-01-01
      • 2011-09-01
      • 2014-08-07
      相关资源
      最近更新 更多