簡體   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