JSFiddle - React, Tailwind, and code Playground
by evankennedy
HTML
<canvas width="200" height="200"></canvas>
<br>
<button id='undo'>Undo</button>
<button id='redo'>Redo</button>
JavaScript
ctx = document.getElementsByTagName('canvas')[0].getContext('2d');
$('#undo').click(function(){
ctx.history.undo();
});
$('#redo').click(function(){
ctx.history.redo();
});
var context = Object.getPrototypeOf(document.createElement('canvas').getContext('2d'));
var canvas = Object.getPrototypeOf(document.createElement('canvas'));
function bind(context, p) {
var original = context[p];
context[p] = function() {
var h = context.history;
if(h.write){
h.data.splice(h.index, h.data.length - h.index, [original, arguments, this]);
h.index++;
}
return original.apply(this, arguments);
};
}
for (var p in context) {
if (context.hasOwnProperty(p)) {
bind(context, p);
}
}
context.redraw = function(){
this.history.write = false;
var context = this.history.data[0][2];
context.clearRect(0,0,context.canvas.width,context.canvas.height);
for (var i = 0; i < this.history.index; i++) {
this.history.data[i][0].apply(context,this.history.data[i][1]);
}
}
context.history = {
index: 0,
data: [],
undo: function() {
if(this.index != 0) this.index--;
context.redraw();
},
redo: function() {
if(this.index != this.data.length) this.index++;
context.redraw();
},
write: true
};
// Filled triangle
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill();
// Stroked triangle
ctx.beginPath();
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath();
ctx.stroke();