KineticJS:使用DragBoundFunc的捕捉功能不适用于所有形状

Sah*_*Ch. 7 collision-detection kineticjs

我实现了一个检测两个形状之间碰撞的函数,以及另一个在检测到碰撞时将dragBound限制为边框的函数,以实现捕捉功能,然后添加到Kinetic.Group.所以实际上我将放置目标限制为现有矩形的边界.

这是一个明确查看我的问题的方法:http://jsfiddle.net/4Y87X/6/

当width = height时,这个逻辑适用于大矩形.但是,当我拖动小灰色矩形(代表我项目中的一个窗口)时,仅在大矩形的右侧和顶部检测到碰撞,未检测到左侧和底部!这是由于DragBoundWindow方法中的一些数学方程吗?

如果有人能找到错误,请?

代码:

var stage = new Kinetic.Stage({
    container: "container",
    width: 900,
    height: 600
});
var leftLayer = new Kinetic.Layer({
    x:0,
    y:0,
    id: 'leftLayer',
    width:250,
    height:600
});
var leftBackground = new Kinetic.Rect({
    width: 250,
    height: 600,
    stroke: "red"
    });
leftLayer.add(leftBackground);
stage.add(leftLayer);

var rightLayer = new Kinetic.Layer({
    x: 280,
    y:0,
    id: 'rightLayer',
    width:600,
    height:600
});
var rightBackground = new Kinetic.Rect({
    x: 0,
    y: 0,
    width: 600,
    height: 600,
    stroke: "green"
    });
rightLayer.add(rightBackground);
stage.add(rightLayer);

//draw a room
var room = new Kinetic.Rect({
    width: 100,
    height: 100,
    fill: 'cornsilk',
    stroke: 'black',
    strokeWidth: 3,
    dragOnTop: false
});

var window = new Kinetic.Rect({
    x: 30,
    y: 250,
    width: 40,
    height: 4,
    name: 'window',
    id: "window_ID",
    fill: '#ccc',
    stroke: 'black',
    strokeWidth: 1
});

var rooms = [];
var id = 0

var group = new Kinetic.Group({
    x: 10,
    y: 100,
    width: 100,
    height: 100,
    id: id++
});
group.add(room);
leftLayer.add(group);
leftLayer.add(window);
stage.draw();

group.on('mousedown touchstart', function(e){
    if (e.which != 3) {
    var cloneOfItem= group.clone({added: false, id: id++});
    cloneOfItem.setDraggable(true);
    cloneOfItem.off('mousedown touchstart');
    leftLayer.add(cloneOfItem);

    cloneOfItem.dragBoundFunc(dragBoundCarre);

    cloneOfItem.on('dragmove', function(){
        this.moveToTop();
    });
    cloneOfItem.on('dragend', function(){
        var userPos = stage.getPointerPosition();
        if (userPos.x>280 && userPos.y>0 && !this.getAttr('added'))
        {
            this.setAttr('added', true);
            this.x(this.x() - 280);
            this.moveTo(rightLayer);
            rooms.push(this);
        }
        else if (userPos.x<280)
        {
            this.destroy();
            rightLayer.draw();
            rooms.splice(this,1);
        }
        stage.draw();
    });
     cloneOfItem.fire('mousedown');
     cloneOfItem.fire('touchstart');
    }
});

window.on('mousedown touchstart', function(e){
    if (e.which != 3) {
    var cw = window.clone({draggable:true});
    leftLayer.add(cw);
    cw.off('mousedown touchstart');

        cw.dragBoundFunc(dragBoundWindow);
    cw.on('dragstart', function(){
        this.startX=this.x();
        this.startY=this.y();
        this.lastPos=this.position();
        this.getParent().moveToTop();
    });
    cw.on('dragmove', function(){
        var pos=this.position();
        this.lastPos = pos;
        rightLayer.draw();
    });
    cw.on('dragend', function(e){
        var userPos = stage.getPointerPosition();
        if (userPos.x > 280 && userPos.y > 0)
        {
            var pos = cw.getAbsolutePosition();
            var x = pos.x;
            var y = pos.y;
            var hit = -1;
            for (var i = 0; i < rooms.length; i++) 
            {
                var c = rooms[i];
                var cpos = c.getAbsolutePosition();
                var cx = cpos.x + room.x();
                var cy = cpos.y + room.y();

                //detect collision
                if (x >= cx && x <= cx + c.width() && y >= cy && y <= cy + c.height()) 
                {
                    hit = i;
                    rooms[hit].off('dragend');
                    this.x(x - rooms[hit].x()-280);
                    this.y(y - rooms[hit].y());
                    this.moveTo(rooms[hit]);
                }
            }
            if (hit < 0)
            {
                this.x(x - 280);
                this.y(y);
                this.moveTo(rightLayer);            
                alert("Window is not in the rigth target. \n\nTry again.");
            }     
        }
        else 
        {
            this.remove();
        }
        rightLayer.draw(this);
        stage.draw();     
    });
    cw.fire('mousedown');
    cw.fire('touchstart');
    cw.fire('dragstart');
    }
    rightLayer.draw();
});

stage.add(rightLayer);
stage.add(leftLayer);
stage.draw();

function dragBoundCarre(pos, event) {
    var collided = doObjectsCollide(pos, this);
    if (collided.length > 1) {
        pos.x = this.getAbsolutePosition().x;
        pos.y = this.getAbsolutePosition().y;
    }
    else if (collided.length === 1) {
        collided = collided[0];
        var colAbsX = collided.getAbsolutePosition().x;
        var colAbsY = collided.getAbsolutePosition().y;
        var tempPos = Object.create(pos);

        tempPos.x -= colAbsX;
        tempPos.y -= colAbsY;

        if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x < 0 && Math.abs(tempPos.x) < collided.width()) {
            pos.x = colAbsX - this.width();
        } else if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x > 0 && Math.abs(tempPos.x) < collided.width()) {
            pos.x = colAbsX + collided.width();
        } else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y < 0 && Math.abs(tempPos.y) < collided.height()) {
            pos.y = colAbsY - this.height();
        } else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y > 0 && Math.abs(tempPos.y) < collided.height()) {
            pos.y = colAbsY + collided.height();
        }

    }
    return {
        x: pos.x,
        y: pos.y
    };
}

function dragBoundWindow(pos, event, group) {
    var collided = doObjectsCollide(pos, this);
    if (collided.length > 1) {
        pos.x = this.getAbsolutePosition().x;
        pos.y = this.getAbsolutePosition().y;
    }
    else if (collided.length === 1) {
        collided = collided[0];
        var colAbsX = collided.getAbsolutePosition().x;
        var colAbsY = collided.getAbsolutePosition().y;
        var tempPos = Object.create(pos);

        tempPos.x -= colAbsX;
        tempPos.y -= colAbsY;

        if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x < 0 && Math.abs(tempPos.x) < collided.width()) {

            pos.x = colAbsX - this.width() + 40;
            //switch width and height          
            this.setWidth(window.getHeight());
            this.setHeight(window.getWidth());
            console.log('collision: left');
        } else if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x > 0 && Math.abs(tempPos.x) < collided.width()) {
            pos.x = colAbsX + collided.width();
            this.setWidth(window.getHeight());
            this.setHeight(window.getWidth());
            console.log('collision: right');
        } else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y < 0 && Math.abs(tempPos.y) < collided.height()) {
            pos.y = colAbsY - this.height();
            this.setWidth(window.getWidth());
            this.setHeight(window.getHeight());            
            console.log('collision: top');
        } else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y > 0 && Math.abs(tempPos.y) < collided.height()) {
            pos.y = colAbsY + collided.height();
            this.setWidth(window.getWidth());
            this.setHeight(window.getHeight());
            console.log('collision: bottom');
        }
    }
    return {
        x: pos.x,
        y: pos.y
    };
    group.add(this);
}

function doObjectsCollide(pos, a) {
    var col = [];
    for (var i = 0; i < rooms.length; i++) {
        var b = rooms[i];
        if (a.id() != b.id()) {
            if (!((pos.y + a.getHeight()) < (b.getAbsolutePosition().y) || (pos.y > (b.getAbsolutePosition().y + b.getHeight())) || ((pos.x + a.getWidth()) < b.getAbsolutePosition().x) || (pos.x > (b.getAbsolutePosition().x + b.getWidth())))) 
            {
                col.push(b);
            }
        }
    }
    return col;
}
Run Code Online (Sandbox Code Playgroud)