Comment créer Undo-Redo dans kineticjs?

Existe-t-il un moyen simple de créer une fonction de refaire l'annulation dans Kineticjs? J'ai trouvé un Undo Manager pour HTML 5 dans https://github.com/ArthurClemens/Javascript-Undo-Manager , mais je ne sais pas comment mettre Kineticjs, aidez-moi. Je vous remercie.

J'ai pu mettre en œuvre une solution simple basée sur un article de Chtiwi Malek chez CodiCode . J'ai également utilisé un certain code de ce problème comme un exemple pour dessiner des rectangles, donc les crédits vont vers eux et Chtiwi.

La seule différence dans ma solution est que j'ai utilisé jSON () pour stocker chaque état de couche dans un tableau au lieu de toDataURL () sur le canevas. Je pense que TOJSON () est nécessaire sur toDataURL () pour pouvoir sérialiser toutes les données nécessaires pour stocker chaque action sur le canevas, mais je ne suis pas à 100%, alors si quelqu'un d'autre sait, laissez un commentaire.

function makeHistory() { historyStep++; if (historyStep < history.length) { history.length = historyStep; } json = layer.toJSON(); history.push(json); } 

Appelez cette fonction chaque fois que vous souhaitez enregistrer une étape pour annuler ou refaire. Dans mon cas, j'appelle cette fonction sur chaque événement mouseup.

Reliez ces 2 fonctions aux événements Undo / Redo.

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

Voici le jsfiddle . N'oubliez pas d'initialiser le tableau et le compteur d'étape en haut. Bonne chance!

Je ne suis pas familier avec KineticJS, mais l'approche devrait être similaire à la démonstration fournie (qui utilise également une toile).

Peut-être qu'un autre exemple vous aide. Disons que j'ai une application pour créer / déplacer / supprimer des formes colorées qui représentent des notes musicales. J'ai un moyen de faire un clic-glisser et de mettre en surbrillance une sélection de notes. Appuyez sur Supprimer sur le clavier pour appeler la fonction surDeleteGroup:

 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' ); } 

Toutes les notes sont supprimées et 2 méthodes sont enregistrées avec le gestionnaire d'annulation:

  1. La fonction d'annulation (annuler la suppression sera créée)
  2. La fonction redo (après annulation / création sera à nouveau effacée)

Les deux fonctions sont simples:

 _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 // ... } 

Comme vous pouvez le voir, l'objet de données (tableau des notes) est transmis pour la création et la suppression. Vous pouvez faire de même pour manipuler des objets singuliers.

J'ai écrit une classe pour la fonctionnalité: http://www.sebastianviereck.de/fr/redo-undo-class-kinetic-js/

Pour résoudre le problème des auditeurs d'événements, travaillez en faisant des 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(); } }; 

Fonctionne parfaitement pour moi.