diff --git a/css/activity.css b/css/activity.css index 5cecaf7..dd533c1 100644 --- a/css/activity.css +++ b/css/activity.css @@ -8,4 +8,12 @@ #main-toolbar #clear-button { background-image: url(../icons/clear-button.svg); -} \ No newline at end of file +} + +#main-toolbar #undo-button { + background-image: url(../icons/undo-button.svg); +} + +#main-toolbar #redo-button { + background-image: url(../icons/redo-button.svg); +} diff --git a/icons/redo-button.svg b/icons/redo-button.svg new file mode 100644 index 0000000..6d976bb --- /dev/null +++ b/icons/redo-button.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/icons/undo-button.svg b/icons/undo-button.svg new file mode 100644 index 0000000..c6d0785 --- /dev/null +++ b/icons/undo-button.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index 3c47fa2..8dca9e7 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,8 @@ + + diff --git a/js/activity.js b/js/activity.js index 995d47a..083923c 100644 --- a/js/activity.js +++ b/js/activity.js @@ -55,6 +55,11 @@ define(function (require) { this.nlabels = []; this.shape = 0; + // Undo/Redo variables + this.strokes = []; + this.undoneStrokes = []; + this.currentStroke = null; + // Image sources this.Star = "images/star.svg"; this.Dot = "images/dot.svg"; @@ -207,11 +212,12 @@ define(function (require) { y: target.y - evt.stageY, }; - // Initialize drawing variables - self.color = self.colors[self.index++ % self.colors.length]; - self.stroke = (Math.random() * 30 + 10) | 0; - self.oldPt = new createjs.Point(self.stage.mouseX, self.stage.mouseY); - self.oldMidPt = self.oldPt; + // Initialize a new stroke + self.currentStroke = { + color: self.color, + strokeSize: self.stroke, + segments: [], + }; evt.onMouseMove = function (ev) { target.x = ev.stageX + offset.x; @@ -233,16 +239,37 @@ define(function (require) { self.oldMidPt.y ); + // Record this segment of the stroke + self.currentStroke.segments.push({ + start: { x: self.oldMidPt.x, y: self.oldMidPt.y }, + control: { x: self.oldPt.x, y: self.oldPt.y }, + end: { x: midPt.x, y: midPt.y }, + }); + self.oldPt.x = self.stage.mouseX; self.oldPt.y = self.stage.mouseY; self.oldMidPt.x = midPt.x; self.oldMidPt.y = midPt.y; }; + + evt.onMouseUp = function () { + // Finalize the current stroke + if (self.currentStroke && self.currentStroke.segments.length > 0) { + self.strokes.push(self.currentStroke); + self.currentStroke = null; + // Clear the redo stack since a new stroke is drawn + self.undoneStrokes = []; + } + }; }; target.onMouseOver = function () { target.scaleX = target.scaleY = target.scale * 1.2; self.update = true; + self.color = self.colors[self.index++ % self.colors.length]; + self.stroke = (Math.random() * 30 + 10) | 0; + self.oldPt = new createjs.Point(self.stage.mouseX, self.stage.mouseY); + self.oldMidPt = self.oldPt; }; target.onMouseOut = function () { @@ -297,6 +324,10 @@ define(function (require) { this.midPt = this.oldPt; this.oldMidPt = this.oldPt; this.update = true; + + // Clear the stroke history + this.strokes = []; + this.undoneStrokes = []; }; DrawingApp.prototype.setupEventListeners = function () { @@ -319,8 +350,58 @@ define(function (require) { clearButton.addEventListener("click", function () { self.clearCanvas(); }); + + // Undo button + var undoButton = document.getElementById("undo-button"); + undoButton.addEventListener("click", function () { + self.undo(); + }); + + // Redo button + var redoButton = document.getElementById("redo-button"); + redoButton.addEventListener("click", function () { + self.redo(); + }); + }; + + // Undo the last stroke + DrawingApp.prototype.undo = function () { + if (this.strokes.length > 0) { + var lastStroke = this.strokes.pop(); + this.undoneStrokes.push(lastStroke); + this.redrawStrokes(); + } + }; + + // Redo the last undone stroke + DrawingApp.prototype.redo = function () { + if (this.undoneStrokes.length > 0) { + var stroke = this.undoneStrokes.pop(); + this.strokes.push(stroke); + this.redrawStrokes(); + } }; - // Export the DrawingApp class - return DrawingApp; + // Redraw all strokes from the history + DrawingApp.prototype.redrawStrokes = function () { + // Clear the drawingCanvas + this.drawingCanvas.graphics.clear(); + + // Redraw each stroke + for (var i = 0; i < this.strokes.length; i++) { + var s = this.strokes[i]; + this.drawingCanvas.graphics + .setStrokeStyle(s.strokeSize, "round", "round") + .beginStroke(s.color); + + for (var j = 0; j < s.segments.length; j++) { + var seg = s.segments[j]; + this.drawingCanvas.graphics + .moveTo(seg.start.x, seg.start.y) + .curveTo(seg.control.x, seg.control.y, seg.end.x, seg.end.y); + } + } + + this.update = true; + }; });