How to add undo-functionality to HTML5 Canvas?

依然范特西╮ 提交于 2019-12-03 06:09:43
Jonas

You have to store all modifications in a datastructure. Then you can delete the latest modification if the user wants to undo it. Then you repaint all drawing operations from your datastructure again.

On http://arthurclemens.github.io/Javascript-Undo-Manager/ I have a working example of undo with a canvas element. When you make a modification, you feed the undo manager the undo and redo methods. Tracking of the position in the undo stack is done automatically. Source code is at Github.

The other option, if you need to manipulate objects is to convert your canvas to SVG using a library that preserves the Canvas API preventing a rewrite.

At least one such library exists at this time (November 2011): SVGKit

Once you have SVG, it is much easier to remove objects and much more without the need to redraw the entire canvas.

Here is a solution that works for me. I have tried it in the latest versions of Firefox and Chrome and it works really well in those two browsers.

var isFirefox = typeof InstallTrigger !== 'undefined';
var ctx = document.getElementById('myCanvas').getContext("2d");
var CanvasLogBook = function() {
    this.index = 0;
    this.logs = [];
    this.logDrawing();
};
CanvasLogBook.prototype.sliceAndPush = function(imageObject) {
    var array;
    if (this.index == this.logs.length-1) {
        this.logs.push(imageObject);
        array = this.logs;
    } else {
        var tempArray = this.logs.slice(0, this.index+1);
        tempArray.push(imageObject);
        array = tempArray;
    }
    if (array.length > 1) {
        this.index++;
    }
    return array;
};
CanvasLogBook.prototype.logDrawing = function() { 
    if (isFirefox) {
        var image = new Image();
        image.src = document.getElementById('myCanvas').toDataURL();
        this.logs = this.sliceAndPush(image);
    } else {
        var imageData = document.getElementById('myCanvas').toDataURL();
        this.logs = this.sliceAndPush(imageData);
    }
};
CanvasLogBook.prototype.undo = function() {
    ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
    if (this.index > 0) {
        this.index--;
        this.showLogAtIndex(this.index);
    }
};
CanvasLogBook.prototype.redo = function() {
    if (this.index < this.logs.length-1) {
        ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
        this.index++;
        this.showLogAtIndex(this.index);
    }
};
CanvasLogBook.prototype.showLogAtIndex = function(index) {
    ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
    if (isFirefox) {
        var image = this.logs[index];
        ctx.drawImage(image, 0, 0);
    } else {
        var image = new Image();
        image.src = this.logs[index];
        ctx.drawImage(image, 0, 0);
    }
};
var canvasLogBook = new CanvasLogBook();

So every time you draw any thing you will there after run function canvasLogBook.logDrawing() to store a snapshot of the canvas and then you can call canvasLogBook.undo() to undo and canvasLogBook.redo() to redo.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!