How to implement HTML5 Canvas undo function

HTML 5 is awesome. My most favorite feature is the canvas. It has many uses and of them is to allow the users of your website to draw free shapes.

If that’s what your website utilizes the canvas element for, by no doubt you have already identified the need for an ‘undo’ function. Perhaps you have already tried the .save() and .restore() functions, only to realize that they only save and restore the fill style of the drawing shapes.

This is exactly the problem I had, while creating my online Rage Comic Editor. Fortunately, I implemented a solution, which I would like to share with you.

The following tutorial assumes that you are familiar with the canvas element and its usage. It will only explain the technique I have discovered to save and restore a canvas drawing state. The implementation is (naturally) in JavaScript.

First, and most important, I have an online demo illustrating the tutorial, here. If you are inpatient or want to get straight to the code, feel free to navigate there and ‘view source’. It is well commented and should be self-explanatory.

In the demo I didn’t bother to implement a ‘free hand drawing’ tool. Instead, I have two buttons only – one of them draw lines on the canvas and the other button undoes one step at a time.

Now to the point… The whole technique consists of three parts:

  1. You need an array, to store the ‘restore points’ (much like Windows Restore Points). We will push states in it, when performing changes on the canvas, and will pop (and restore) states, out of it, when we press the ‘undo’ button. Here is how I have declared it: var restorePoints = [];
  2. As mentioned, before performing any change on the canvas, we need to store its state. We do this, by calling the toDataURL of the canvas, which exports the current drawing in your canvas, to a (PNG) image, encoded as base64. Basically, we ask the canvas to give us a text representation of the image that is drawn. Now we only need to insert this text, as an element of our restorePoints array. We do this using the restorePoints.push(…) command. The implementation of this step is in the saveRestorePoint() function in the example. Again – you have to call this method, before performing a change on the canvas!
  3. Now, how do we restore the canvas to its previous state, when the user clicks on an ‘undo’ button? We call a javascript method in which we have to create a new Image object in the memory, set its ‘src’ property to the last element in the restorePoints array (we do this using the array pop() method, which also removes the element from the array – exactly what we need!) and draw this image on the canvas (using the drawImage() function). So effectively what we do is: we take the last restoration point (image) and overlay it on top of the current state of the canvas. This will cause the effect of removing only the last change on your canvas, because we have restored to a point, which is previous to that change. We also need to remove the restoration point from the array, because we are currently ‘in it’ anyway.

And that’s about it. To summarize: maintain a javascript array of the previous states of the canvas. Before you perform a change on the canvas, save the current state, by exporting the canvas to a base64 encoded image. Store that state in the array of states, then do your change. When you want to ‘undo’, .pop() the last state from the canvas and draw it on top of everything. This will overwrite the whole canvas, but will only remove your last change, because the restoration point is before it.

I think there is no better explanation than a code sample, so go ahead and view the source of the demo. You can download the complete solution from here.

Cheers and Merry Christmas!

Advertisements