0

这些是按钮功能:

$("#undo").click(function() {
    Stack1.undo();
});

$("#redo").click(function() {
  Stack1.redo();
});

这是撤消功能:

    function clearCanvas()
    {
    ctx.clearRect(0,0,canvasWidth,canvasHeight);

    }
   Stack1 = new Stack();
    ///////////////////

    function Stack(firstImg , size) {
    var drawStack = new Array();
    var stackIndex = 0;
    var stackTop = 0;
    var stackFloor = 0;
    var stackSize = size; 

    drawStack[0] = firstImg;

this.add = function() {
    drawStack[++stackIndex%stackSize] = canvas.toDataURL("image/png");
    if (stackIndex >= stackSize) stackFloor = (stackIndex +1) % stackSize ;
    stackTop = stackIndex % stackSize;
}

this.undo = function () {
    if (stackIndex%stackSize == stackFloor ) return;
    clearCanvas();
    var tmpImg = new Image();
    tmpImg.src = drawStack[--stackIndex%stackSize];
    ctx.drawImage(tmpImg, 0, 0);

}

this.redo = function () {
    if (stackIndex%stackSize == stackTop) return;
    clearCanvas();
    var tmpImg = new Image();
    tmpImg.src = drawStack[++stackIndex%stackSize];
    ctx.drawImage(tmpImg, 0, 0);
}
} 

我还在顶部声明了数组:

var drawStack = [];

我还在鼠标按下方法中绘制每个笔划之前放置了这段代码:

 Stack1.add();

这是我的工作示例..在屏幕上绘制 3 个圆圈然后单击撤消,一切都变为空白,然后再次单击它,只剩下 2 个。它很接近,但我无法弄清楚最后一部分。

4

1 回答 1

0

你让这变得比它需要的更复杂。撤消功能通常如何工作的伪代码如下:

currentState = 0
maxStates = 10
stateArray = []

initialize:
   push the current state onto the top of stateArray 

save:
  if there are states in stateArray above the currentState
    clear the states in stateArray above the current state
  push the current state onto the top of stateArray 
  currentState++
  if the size of stateArray exceeds maxStates
     remove the oldest state from the bottom of stateArray 
     currentState--

undo:
  if there are previous states in stateArray 
    currentState--
    revert the canvas to stateArray[currentState]

redo:
  if there are newer states in stateArray 
     currentState++
     revert the canvas to stateArray[currentState]

如你看到的:

  • 您永远不需要 mod 运算符。
  • 您不需要跟踪堆栈的顶部和底部,只需跟踪当前状态的索引、您想要的状态数和 stateArray 的大小。
  • 当您添加一个新状态以使其按人们期望的方式运行时,您应该清除当前状态上方的 stateArray 中的状态(除非您要实现大多数应用程序没有的分支历史)。

编辑:我注意到您的代码中有一个不同的问题,您正试图立即将图像绘制到画布上,而不是等待它加载。至少您的撤消功能应如下所示:

this.undo = function () {
    if (stackIndex%stackSize == stackFloor) return;
    var tmpImg = new Image();
    tmpImg.src = drawStack[--stackIndex%stackSize];
    tmpImg.onload = function() {
       clearCanvas();
       ctx.drawImage(this, 0, 0);
    }
}

如果您的索引是正确的,我怀疑它们不是。您可以在这个 fiddle中查看我上面描述的算法的示例实现。

于 2013-06-17T17:32:07.023 回答