Is there any simple way how to create undo redo function in Kineticjs ? I have found a Undo Manager for HTML 5 in https://github.com/ArthurClemens/Javascri
i have written a class for the functionality: http://www.sebastianviereck.de/en/redo-undo-class-kinetic-js/
To solve event listeners problem, work on by making clones
$scope.makeHistory=function() {
$scope.historyStep++;
if ($scope.historyStep < $scope.history.length) {
$scope.history.length = $scope.historyStep;
}
var layerC = $scope.topLayer.clone();
$scope.history.push(layerC);
};
$scope.undoObject = function(){
if($scope.historyStep > 0) {
$scope.historyStep--;
$scope.topLayer.destroy();
if($scope.historyStep==0){
$scope.topLayerAdd(2); // will put empty layer
}
else{
var layer = $scope.history[$scope.historyStep-1].clone();
$scope.topLayerAdd(1,layer);
}
$scope.topLayer.draw();
}
};
$scope.redoObject = function(){
if($scope.historyStep <= $scope.history.length-1) {
$scope.historyStep++;
$scope.topLayer.destroy();
var layer = $scope.history[$scope.historyStep-1].clone();
if($scope.historyStep==0){
$scope.topLayerAdd(2); // will put empty layer
}
else{
$scope.topLayerAdd(1,layer);
}
$scope.topLayer.draw();
}
};
works perfectly for me.
I was able to implement a simple solution based on a post by Chtiwi Malek at CodiCode. I also used some of the code from this problem as an example to draw rectangles, so credits go to them and Chtiwi.
The only difference in my solution is I used toJSON() to store each layer state in an array instead of toDataURL() on the canvas. I think toJSON() is needed over toDataURL() to be able to serialize all the data necessary to store each action on the canvas, but I'm not 100% on this so if someone else knows please leave a comment.
function makeHistory() {
historyStep++;
if (historyStep < history.length) {
history.length = historyStep;
}
json = layer.toJSON();
history.push(json);
}
Call this function everytime you want to save a step to undo or redo. In my case, I call this function on every mouseup event.
Bind these 2 functions to the Undo/Redo events.
function undoHistory() {
if (historyStep > 0) {
historyStep--;
layer.destroy();
layer = Kinetic.Node.create(history[historyStep], 'container')
stage.add(layer);
}
}
function redoHistory() {
if (historyStep < history.length-1) {
historyStep++;
layer.destroy();
layer = Kinetic.Node.create(history[historyStep], 'container')
stage.add(layer);
}
}
Here's the jsfiddle. Don't forget to initialize the array and step counter up top. Good luck!
I am not familiar with KineticJS, but the approach should be similar to the provided demo (that also uses a canvas).
Perhaps another example helps. Let's say I have an app to create/move/delete colored shapes that represent musical notes. I have a way to click-drag and highlight a selection of notes. Pressing Delete on the keyboard invokes the function onDeleteGroup:
onDeleteGroup: function(gridModel) {
// collect all notes in an array
// ...
this._deleteGroup(notes);
this.undoManager.register(
this, this._createGroup, [notes], 'Undo delete',
this, this._deleteGroup, [notes], 'Redo delete'
);
}
All notes are deleted, and 2 methods are registered with the undo manager:
Both functions are straightforward:
_deleteGroup:function(notes) {
// removes each note from the model
// thereby removing them from the canvas
// ...
}
_createGroup:function(notes) {
// add each note to the model
// thereby adding them to the canvas
// ...
}
As you can see, the data object (array of notes) is passed around for creation and deleting. You can do the same for manipulating singular objects.