Skip to content

Dragging multiple layers in JavaScript with KineticJS

I’m trying to synchronize dragging of multiple layers. Example here: http://jsfiddle.net/e8Z3a/

var stage = new Kinetic.Stage({
  container: document.getElementById('canvas'),
  width: 600,
  height: 600
});

var imageLayer = new Kinetic.Layer();
stage.add(imageLayer);

var imageObj = new Image();
imageObj.src = 'http://laughingsquid.com/wp-content/uploads/Tard2.jpg';

imageObj.onload = function () {
  var image = new Kinetic.Image({
      image: imageObj
  });

  imageLayer.add(image);
  imageLayer.setWidth(imageObj.naturalWidth);
  imageLayer.setHeight(imageObj.naturalHeight);

  imageLayer.draw();
};


var drawingLayer = new Kinetic.Layer();
stage.add(drawingLayer);

var mustache = new Kinetic.Polygon({
  points: [
    380, 380,
    410, 350,
    380, 390,
    210, 390,
    180, 350,
    210, 380
  ],
  fill: 'black'
});

drawingLayer.add(mustache);
drawingLayer.draw();

var posX, posY;
imageLayer.on('dragstart', function(event) {
  posX = event.clientX;
  posY = event.clientY;
});

imageLayer.on('dragmove dragend', function(event) {
  drawingLayer.move(event.clientX - posX, event.clientY - posY);
  drawingLayer.draw();

  posX = event.clientX;
  posY = event.clientY;
});

imageLayer.setDraggable(true);

The problem is the sync is missing some events. After doing a series of short drags, the mustache layer stays behind, as if it was missing some events on the way.

My observation leads to a guess, that fast dragging works. I mean if you grab the image without moving the mouse, move quickly in random directions, stop the mouse and then let go, layers stay in sync. The problem is with grabbing and letting go while the mouse moves.

Can you teach me how to debug this kind of problems? Is there a TDD-like approach for events related stuff? Any way to maybe record a series of events and than replay it, while adding some debug code? Classic step-by-step debugging is quite useless here…

Answer

I would go simple,

imageLayer.on('dragmove', function() {
    drawingLayer.setAttrs({x:this.getX(), y:this.getY()});
    drawingLayer.draw();
});

My example, http://jsfiddle.net/QTu8K/38 (updated)