Search code examples
javascriptcanvasdrawingundo-redo

My undoTheUndo in a drawing program can't do it on circles but on lines


I am making a drawing program, where you can draw, undo your last action and undo the undo of your last action. EG: helo (drawing, action I) ---D hello (drawing action II) ---D helo (Undoing) ---D hello (Undoing the undo I did). Here is my code in action : Click here
Here is my javascript :

var ctx = document.getElementById("canvasId").getContext("2d");
var DrawnSaves = new Array();
var Undo = new Array();
var FigureNumber = -1;
var deletingTimer;

function drawLine(startX, startY, destX, destY) {
  ctx.beginPath();
  ctx.moveTo(startX, startY);
  ctx.lineTo(destX, destY);
  ctx.stroke();
  var Para = new Array();
  Para["type"] = "line";
  Para["fromX"] = startX;
  Para["fromY"] = startY;
  Para["toX"] = destX;
  Para["toY"] = destY;
  DrawnSaves.push(Para);
  FigureNumber++;
}

function drawCircle(X, Y, radius) {
  ctx.beginPath();
  ctx.arc(X, Y, radius, 0, Math.PI * 2);
  ctx.stroke();
  var Para = new Array();
  Para["type"] = "circle";
  Para["x"] = X;
  Para["y"] = Y;
  Para["radius"] = radius;
  DrawnSaves.push(Para);
  FigureNumber++;
}

function undo() {
  ctx.beginPath();
  ctx.clearRect(0, 0, 500, 300);
  Undo[FigureNumber] = DrawnSaves[FigureNumber];
  DrawnSaves[FigureNumber] = "deleted";
  FigureNumber--;
  drawEverything();
  startTimeoutOfDeleting();
}

function undoTheUndo() {
  FigureNumber++;
  DrawnSaves[FigureNumber] = Undo[FigureNumber];
  drawEverything();
  clearTimeout(deletingTimer);
}

function drawEverything() {
  for (i = 0; i < DrawnSaves.length; i++) {
    if (DrawnSaves[i].type == "line") {
      ctx.beginPath();
      ctx.moveTo(DrawnSaves[i].fromX, DrawnSaves[i].fromY);
      ctx.lineTo(DrawnSaves[i].toX, DrawnSaves[i].toY);
      ctx.stroke();
    } else if (DrawnSaves[i].type == "circle") {
      ctx.beginPath();
      ctx.arc(DrawnSaves[i].x, DrawnSaves[i].y, DrawnSaves[i].radius, 0, Math.PI * 2);
    }
  }
}

function startTimeoutOfDeleting() {
  setTimeout(function() {
    Undo[FigureNumber] = "deleted";
  }, 5000);
}

Solution

  • You code is fine, its the test lines that are causing the issue.

    setTimeout(function() {    
      drawCircle(100, 100, 25);
      setTimeout(function() {}, 1000);
      setTimeout(function() {
        undo(); // You forgot this undo() here
      }, 1000);
      setTimeout(function() {
        undoTheUndo();
      }, 2000);
    }, 3000);
    

    I would suggest adding a check for undefined, like so:

    function undoTheUndo() {
      FigureNumber++;
      if (Undo[FigureNumber] !== undefined) {
        DrawnSaves[FigureNumber] = Undo[FigureNumber];
      }
      drawEverything();
      clearTimeout(deletingTimer);
    }
    

    Also, I made this chance when initializing the circles and lines.

    FigureNumber++;
    DrawnSaves[FigureNumber] = Para;
    

    JSFiddle