Как добавить отменную функциональность к холсту HTML5?

У меня есть приложение Sketching, выполненное во всех HTML5 и Javascript, и мне было интересно, как создать кнопку "Отменить", чтобы вы могли отменить последнее, что вы нарисовали. Любая идея?

Ответ 1

Вы должны сохранить все изменения в структуре данных. Затем вы можете удалить последнюю модификацию, если пользователь хочет отменить. Затем вы снова перерисовываете все операции рисования из своей структуры данных.

Ответ 2

Вкл http://arthurclemens.github.io/Javascript-Undo-Manager/ У меня есть рабочий пример отмены с элементом холста. Когда вы вносите изменения, вы подаете команду отмены для отмены и повтора. Отслеживание позиции в стопке отмены выполняется автоматически. Исходный код находится в Github.

Ответ 3

Другим вариантом, если вам нужно манипулировать объектами, является преобразование вашего холста в SVG с использованием библиотеки, которая сохраняет Canvas API, предотвращая переписывание.

В настоящее время существует хотя бы одна такая библиотека (ноябрь 2011 г.): SVGKit

Как только у вас есть SVG, гораздо проще удалить объекты и многое другое без необходимости перерисовывать весь холст.

Ответ 4

Вот решение, которое работает для меня. Я пробовал его в последних версиях Firefox и Chrome, и он отлично работает в этих двух браузерах.

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();

Итак, каждый раз, когда вы рисуете какую-либо вещь, вы будете после выполнения функции canvasLogBook.logDrawing(), чтобы сохранить снимок холста, а затем вы можете вызвать canvasLogBook.undo() для отмены и canvasLogBook.redo() для повтора.