繁体   English   中英

绘画画布撤消功能

[英]Paint canvas undo feature

这些是按钮功能:

$("#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个。 它很接近,但我无法弄清最后一部分。

您已经使它变得比所需复杂。 有关撤消功能通常如何工作的伪代码如下:

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);
    }
}

如果您的索引正确,我怀疑它们不合适。 您可以在小提琴中查看我上面描述的算法的示例实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM