Search code examples
javascripthtmlcanvaskineticjs

How to restrict image drag using KineticJS?


FIDDLE: http://jsfiddle.net/x6BPK/

I am using KineticJS to add an image into a group and then a rectangle into the group. I want to be able to drag the rectangle only within the bounds of the group. First I created the group and placed the image inside:

//Set up Kinetic

Kinetic.pixelRatio = 1;

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

var layer = new Kinetic.Layer();

stage.add(layer);

function placeImage(insertImage) {
    //Place image on canvas

    var imageObj = new Image();

    imageObj.onload = function() {
        xCoord = imageObj.width / 2;
        yCoord = imageObj.height / 2;

        var piece = new Kinetic.Image({
            image:imageObj,
            width:500,
            height:500
        });

        var pieceGroup = new Kinetic.Group({
            x: xCoord,
            y: yCoord,
            offsetX: imageObj.width / 2,
            offsetY: imageObj.height / 2,
            id:'image',
            offsetX: imageObj.width / 2,
            offsetY: imageObj.height / 2,
            draggable:true
        });

        pieceGroup.add(piece);
        layer.add(pieceGroup);
        stage.add(layer);

        addRect();
    };

    imageObj.src = insertImage;
}

placeImage("http://emboldenmedia.com/staging/astrocollage/img/library/planets/pla1.png");

Then I added the rectangle with the dragBoundFunc listed. The function just doesn't work however. Any improvements I can make? Here is a fiddle: http://jsfiddle.net/x6BPK/

function addRect() {
    var astroElement = stage.find('#image');

    var adjWidth = astroElement[0].children[0].attrs.image.width;
    var adjHeight = astroElement[0].children[0].attrs.image.height;

    console.log(astroElement);

    var rect = new Kinetic.Rect({
        x:astroElement[0].attrs.x,
        y:astroElement[0].attrs.y,
        offsetX:adjWidth / 2,
        offsetY:adjHeight / 2,
        width:300,
        height:300,
        stroke:"blue",
        strokeWidth:4,
        draggable:true,
        id:'cropRect',
        dragBoundFunc:function(pos) {
            var X = pos.x;
            var Y = pos.y;
            if (X < minX) {
                X = minX;
            }
            if (X > maxX) {
                X = maxX;
            }
            if (Y < minY) {
                Y = minY;
            }
            if (Y > maxY) {
                Y = maxY;
            }
            return {
                x:X,
                y:Y
            }
        }
    });

    var minX = astroElement.getX();
    var maxX = astroElement.getX() + astroElement.getWidth() - rect.getWidth();
    var minY = astroElement.getY();
    var maxY = astroElement.getY() + astroElement.getHeight() - rect.getHeight();

    astroElement.add(rect);

    layer.draw();
}

Solution

    1. find(selector) returns collection. So you can not do this

      stage.find('#image').getX();
      
    2. Kinetic.Group has no width and height (equals 0). In your case you may use width of image for group width.

      astroElement.find('Image')[0].getWidth()
      

    http://jsfiddle.net/x6BPK/1/