HTML5 Canvas & KineticJS layer order switches on r

2019-08-28 15:49发布

问题:

I am building an animation with HTML5 Canvas and KineticJS. The animation works just fine. However, I've noticed that sometimes on refresh, the layer order of the images I am animating gets rearranged. This switch in layer order seems to happen at random. For instance, I can click refresh 5 times and the layer order is fine... click refresh another 3 times and the layer order rearranges. Can anyone help as to why this random switch in layer order occurs?

回答1:

This is your problem right here:

mac3rdpieceImageObj.onload = function () {
    // add the kinetic image to the layer
    mac3rdpieceLayer.add(mac3rdpiece);
    // add the layer to the stage
    myAnimateStage.add(mac3rdpieceLayer);
};

mac2ndpieceImageObj.onload = function () {
    // add the kinetic image to the layer
    mac2ndpieceLayer.add(mac2ndpiece);
    // add the layer to the stage
    myAnimateStage.add(mac2ndpieceLayer);
};

mac1stpieceImageObj.onload = function () {
    // add the kinetic image to the layer
    mac1stpieceLayer.add(mac1stpiece);
    // add the layer to the stage
    myAnimateStage.add(mac1stpieceLayer);
};

If you disable your browser cache, the problem will occur more often. Using these 3 onload functions, you have no way of controlling which image loads first. Chances are they'll load in order, but sometimes they won't. Whichever order they load in, that layer will be added first, and so sometimes they are out of order.

If you must use 3 different layers for your 3 images, you can fix this issue by adding the layers in order OUTSIDE of the onload functions:

myAnimateStage.add(mac3rdpieceLayer); //Add this layer to the stage first,
myAnimateStage.add(mac2ndpieceLayer); //Then this layer.
myAnimateStage.add(mac1stpieceLayer); //Then this layer. This is the top layer because it was added last.

mac3rdpieceImageObj.onload = function () {
    mac3rdpieceLayer.add(mac3rdpiece);
    mac3rdpieceLayer.draw();
};

mac2ndpieceImageObj.onload = function () {
    mac2ndpieceLayer.add(mac2ndpiece);    
    mac2ndpieceLayer.draw();
};

mac1stpieceImageObj.onload = function () {
    mac1stpieceLayer.add(mac1stpiece);    
    mac1stpieceLayer.draw();
};

This guarantees the order that the layers are added in.

You also need to use the draw() function on each layer after the image loads, so that you can see the image on the canvas. Here's the updated jsfiddle

Suggestion:

Instead of using 3 layers for your 3 images, use 1 Layer and 3 Groups with each Group containing 1 image (and anything else you need to add within each Group). Like this:

var macLayer = new Kinetic.Layer();
myAnimateStage.add(macLayer);

var mac1stpieceGroup = new Kinetic.Group({
  //I suggest moving each image's (x,y) coordinates inside their group
});
var mac2ndpieceGroup = new Kinetic.Group({
  //And using x:0, y:0 for the actual image coordinates
});
var mac3rdpieceGroup = new Kinetic.Group({
  //That way the group holds the position, and you only have to manage one coordinate per group/image
});

macLayer.add(mac3rdpieceGroup); //Here's the order of your groups
macLayer.add(mac2ndpieceGroup);
macLayer.add(mac1stpieceGroup);

mac3rdpieceImageObj.onload = function () {
    mac3rdpieceGroup.add(mac3rdpiece);
    macLayer.draw();
};

mac2ndpieceImageObj.onload = function () {
    mac2ndpieceGroup.add(mac2ndpiece);    
    macLayer.draw();
};

mac1stpieceImageObj.onload = function () {
    mac1stpieceGroup.add(mac1stpiece);    
    macLayer.draw();
};

See this question for more information: What are the differences between group and layer in KineticJs

Final Note:

As a last alternative, you could probably also use the zIndex property to order which layer (or group!) should appear on top of the others. Kinetic.Container#setZIndex