KineticJS Undo layers: layers don't disappear

2019-03-03 23:48发布

I have a specific problem on my designer drawing tool in Canvas HTML5. I am developing an action history system (Undo & Redo). I am building my system on projeqht's answer on this question with serializing the layers in history array. The core, the idea of the solution is working but I have a strange problem. When I hit Undo it creates the new layers, but the old ones are not disappearing. I will attach my sourcecode and I will attach screenshots as well so you can see what is happening:

Sourcecode:

var history = Array(null);

var historyStep = 0;

var arrayNonRemovable = Array('moveLayer', 'scaleFromOuterNode', 'scaleFromInnerNode', 'rotateFromOuterSign', 'rotateFromInnerSign' );

function removeLayerByUndoRedo(l) { if (l) { l.destroy(); l.draw(); stage.draw(); } }

function makeHistory(layer, before, after, operation) { historyStep++; if (historyStep

function undoHistory() { if (historyStep>0) { version = history[historyStep]; layer = version.layer; var beforeState = history[historyStep].before;

    removeLayerByUndoRedo(layer);
    var layer = Kinetic.Node.create(beforeState, 'container');
    stage.add(layer);

    stage.draw();
    historyStep--;
}

}

Array.prototype.contains = function(obj) { return this.indexOf(obj) > -1; };

Screenshots: Step 1. create the object, which contains more groups with shapes inside (lines, rectangles, SVG drawing) Creating object Steps 2, 3, 4, 5: Moving object to different positions (top left, bottom left, bottom right and top right): enter image description here enter image description here enter image description here enter image description here Step 6: Press Undo for first time (removes the old layer well and recreates it from history well): enter image description here Step 7: Press Undo for second time (creates new layer from history, but old layer is not removed) enter image description here Step 8, 9: Press Undo for another 2 times (same happens as in Step 7: creates new layer but old ones remain): enter image description here

Am I doing something wrong? I think it must be something with the reference to the new layers as in Step 6 the removed layers reference is the original layer, in the following steps those are new layers, so reference should be a new one?

2条回答
聊天终结者
2楼-- · 2019-03-04 00:31

Here's what the probloem was: I store the layer reference in the history array. So when I create an object the layer reference is stored in history[1]. I move it to 3 times, I will have the same reference in the history for all the steps. When I press undo, I am destroying the layer calling it from the stored reference and I create a new one which reference is a new one. In the history I still have the old reference, which points to NULL. This was the problem.

I have fixed it destroying the old layer calling it by name. (This only works if you give unique names to layers): stage.find('.'+layer.getName())[0].destroy()

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-03-04 00:33

After you serialize the layer to JSON, you must do

yourLayer.destroy()

Your code seems to do this so I would need more code to find what's going wrong.

A long-shot possibility:

I see that your undoHistory references a global layer and also creates a local layer. Try refactoring your code like this to be sure you're not mixing different "layer":

function undoHistory(){
   if (historyStep>0){
      var version = history[historyStep];
      var beforeState = history[historyStep].before;
      var layer1 = version.layer;
      removeLayerByUndoRedo(layer1);
      var layer2 = Kinetic.Node.create(beforeState, 'container');
      stage.add(layer2);
      stage.draw();
      historyStep--;
    }
}

You don't need to do l.draw() or stage.draw() after l.destroy() because the layer is being destroyed anyway and the stage is auto-updated when the layer is destroyed.

Here is a working example of layer.destroy that may help until you can post more code:

http://jsfiddle.net/m1erickson/FSBbN/

查看更多
登录 后发表回答