1
votes

I am trying to use KineticJS to build a simple strategy game. I have one Kinetic.Stage resized to fit the entire screen. On that stage I intend to have three rendering layers in general. Top most the HUD layer showing the game stats - obviously not draggable. One layer below is the "Action Layer", where the game map an all the action is to be displayed. On the bottom is a static background layer, displaying some kind of a backdrop - uninteresting in this example. I intend to have my action layer draggable in order to scroll around the map. The problem is, it doesn't seem to work this way, the action layer can't be dragged. I must be missing something.

I have reproduced the problem in a fiddle here:

http://jsfiddle.net/shadowfire/2v9xS/22/

Also I have found out, that adding a shape to the root of the action layer allows dragging of the layer - but only if you drag that shape, which doesn't seem to be great solution.

The corresponding code:

var stage = new Kinetic.Stage({
    container: 'myCanvas',
    width: 400,
    height: 400,
    draggable: false,
    listening: true
}); 

var backgroundLayer = new Kinetic.Layer({draggable: false});
var actionLayer = new Kinetic.Layer({draggable: true, listening: true});
var mapLayer = new Kinetic.Layer({draggable: true});
var foregroundLayer = new Kinetic.Layer({draggable: true, clearBeforeDraw: false});
var hudLayer = new Kinetic.Layer({draggable: false});

backgroundLayer.add(new Kinetic.Rect(
    {
        x:0,
        y:0,
        width: 400,
        height: 400,
        fill: 'grey'
    }
));

mapLayer.add(new Kinetic.Rect(
    {
        x:100,
        y:100,
        width: 200,
        height: 200,
        fill: 'orange',
        stroke: 'black',
        draggable: true
    }
));

foregroundLayer.add(new Kinetic.Circle(
    {
        x:200,
        y:200,
        radius: 30,
        fill: 'yellow',
        stroke: 'black',
        draggable: true
    }
));

actionLayer.add(mapLayer);
actionLayer.add(foregroundLayer);
actionLayer.add(new Kinetic.Text({text:"ActionLayer - draggable works only here", fill:'green', x:100, y:100}));

hudLayer.add(new Kinetic.Text(
    {
        fontSize: 30,
        text: 'STATUS',
        fill: 'green'
    }
));

stage.add(backgroundLayer);
stage.add(actionLayer);
stage.add(hudLayer);
2

2 Answers

1
votes

The main problem in my opinion come from the fact that you include layer into layer. The draggable get mess up. this post is a possible explanation of the bug. Plus the fact that you set the whole stage as listening:false. If you just remove the listening:false from the stage you'll see that you can drag your actionLayer by dragging on the text of this layer and only this area.

A workaround if you want only the whole layer to be draggable is to change the mapLayer and foregroundLayer into group. I am not sure what exactly you want but on this fiddle I did set the actionLayer draggable and such as when you drag on the mapLayer you in fact drag the actionLayer and when you drag on the foregroundlayer you only drag this group.

var mapLayer = new Kinetic.Group();

var foregroundLayer = new Kinetic.Group({draggable:true});

If you only want to drag the whole layer whenever you drag anything in it just remove draggable:true in the foregroundlayer.

Hope it helps.

1
votes

Surprisingly, I couldn't get Kinetic.Layer to drag neither, even in the most basic example: http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-the-stage-with-kineticjs/ I tried switching the draggable from the stage to the layer. I even thought that maybe it was because there was no height, width, x, y was specified so I added those in like this:

var layer = new Kinetic.Layer({
  draggable: true,
  x:0,
  y:0,
  width:578,
  height:200,
  visible:true,
  listening: true
});

but still it didn't work like dragging a stage works! Really strange considering the docs say a layer has the property draggable http://kineticjs.com/docs/Kinetic.Layer.html.

Anyways as an alternative, I would suggest adding a master Kinetic.Group to the layer that will hold all your objects, and set that master Group to draggable: true. Then I would add a rectangle that acts as a background to the master Group with the same width and height as the layer, this gives the group a height and width, so that you can drag the entire layer. Then you can add all other elements that belong to the Action layer to that group. Something like this:

var masterGroup = new Kinetic.Group({
  x: actionLayer.getX(),
  y: actionLayer.getY(),
  draggable: true,
  name: "masterGroup"
});

actionLayer.add(masterGroup);

var actionBG = new Kinetic.Rect({
  width: actionLayer.getWidth(),
  height: actionLayer.getHeight(),
  draggable: true,
  name: "actionBG"
});

masterGroup.add(actionBG);
//masterGroup.add(moreActionLayerObjects);

The group will be draggable, and hold all objects inside that also need to be draggable.