2016-08-23 162 views
0

我正在使用KineticJS并尝试完成一些看起来很简单的操作:尝试使用当前正在拖动的形状来改变位置。KineticJS - 在触点/鼠标移动触发器上交换形状位置

想法是:
•您在画布上选取一个形状。这将触发mousedown事件侦听器,该事件侦听器将保存您拾取的形状的当前位置。
•保持形状时,如果在另一个形状上触发mouseover,则会根据当前形状的保存位置触发该形状的事件并交换其位置。

下面是相关的代码,我写来试图获取工作:

板的设置: 只是简单地设立董事会,这里调用所需的功能。我没有对stage,gameBoard或ctx做任何事情(部分原因是当我试图让drawImage在多个画布上工作,但现在已经放弃了这一点)。

class BoardView { 
    constructor(stage, gameBoard, ctx) { 
    this.stage = stage; 
    this.gameBoard = gameBoard; 
    this.ctx = ctx; 
    this.orbs = [[], [], [], [], []]; 
    this.setupBoard(); 
    } 

局设置功能: 这是我去设立董事会,给予每个动力学圈需要渲染的图层的属性。也许我在这里错过了很明显的东西?

setupBoard() { 
    for (let colIdx = 0; colIdx < 5; colIdx++) { 
     this.addRow(colIdx); 
    } 

    this.renderBoard(); 
    } 

    addRow (colIdx) { 
    for (let rowIdx = 0; rowIdx < 6; rowIdx++) { 
     let orbType = Math.round(Math.random() * 5); 
     let orbColor; 

     if (orbType === 0) { 
      orbColor = "#990000"; 
     } else if (orbType === 1) { 
      orbColor = "#112288"; 
     } else if (orbType === 2) { 
      orbColor = "#005544"; 
     } else if (orbType === 3) { 
      orbColor = "#776611"; 
     } else if (orbType === 4) { 
      orbColor = "#772299"; 
     } else { 
      orbColor = "#dd2277"; 
     } 
     let orbject = new Kinetic.Circle({ 
     x: (rowIdx + 0.5) * 100, 
     y: (colIdx + 0.5) * 100, 
     width: 100, 
     height: 100, 
     fill: orbColor, 
     draggable: true 
     }); 
     this.orbs[colIdx].push(orbject); 
    } 
    } 

局渲染功能: 这是我添加的所有动力学对象圈到新的图层,并给这些层所有自己的属性与当我打电话的事件处理工作。在将图层添加到舞台后,我还在此处设置了事件处理程序。我可能通过添加太多图层来搞乱了这一点?

renderBoard() { 

    for (let row = 0; row < this.orbs.length; row++) { 
     for (let orb = 0; orb < this.orbs[row].length; orb++) { 
     let layer = new Kinetic.Layer(); 

     layer.add(this.orbs[row][orb]); 
     layer.moving = false; 
     layer.orbId = `orb${row}${orb}`; 
     layer.pos = [this.orbs[row][orb].attrs.x, this.orbs[row][orb].attrs.y]; 

     this.stage.add(layer); 

     layer.on("mousedown", this.handleMouseDown); 
     layer.on("mouseup", this.handleMouseUp); 
     layer.on("mouseout", this.handleMouseOut); 
     layer.on("mousemove", this.handleMouseMove); 
     } 
    } 
    } 

鼠标事件处理程序: 这是我觉得我有我的主要问题。我如何处理移动鼠标来改变球体的事件,或许我正在做一些非常错误的事情?

handleMouseDown (e) { 
    window.currentOrb = this; 
    console.log(window.currentOrb.orbId); 

    this.moving = true; 
    } 

    //handleMouseUp (e) { 
    // window.currentOrb = undefined; 
    // this.moving = false; 
    //} 

    //handleMouseOut (e) { 
    //} 

    handleMouseMove (e) { 
    if (window.currentOrb !== undefined && window.currentOrb.orbId != this.orbId) { 
     this.children[0].attrs.x = window.currentOrb.pos[0]; 
     this.children[0].attrs.y = window.currentOrb.pos[1]; 
     this.children[0].draw(); 
    } else { 
    } 
    } 
} 


module.exports = BoardView; 

我试过在KineticJS文档和许多StackOverflow的答案寻找,因为我可以找到一个解决方案,为我工作的希望,但没有我见过,并试图到目前为止(包括建议当我写这个问题时出现)似乎有帮助,而且我意识到我迄今为止的这种做法可能远没有达到我想要的最佳方式,所以我对任何人都是开放的建议,指针,回答的问题,或任何可以指向我正确的方向,我失去了什么,才能得到这个工作。

如果这有帮助,这里也是一个可视化的东西,当董事会呈现时的样子。

enter image description here

圆圈都是动力学圈(球体什么我要去为我的目的),然后单击并拖动一个到另一个,就是没有被拖动的一个,但盘旋应该移动拖到被拖动圆圈的原始位置。

谢谢!

编辑:

我做了,因为再对代码进行一些更改。首先,我改变了增加多层次的阶段,到只有一个:

renderBoard() { 
    let layer = new Kinetic.Layer(); 

    for (let row = 0; row < this.orbs.length; row++) { 
    for (let orb = 0; orb < this.orbs[row].length; orb++) { 

     layer.add(this.orbs[row][orb]); 

     this.orbCanvases.push(orbCanvas.id); 
    } 
    } 
    this.stage.add(layer); 
} 

我,而不是添加监听到ORB对象,而不是:

addRow (colIdx) { 
    for (let rowIdx = 0; rowIdx < 6; rowIdx++) { 

    //same code as before 

    let orbject = new Kinetic.Circle({ 
     x: (rowIdx + 0.5) * 100, y: (colIdx + 0.5) * 100, 
     width: 100, height: 100, 
     fill: orbColor, draggable: true, pos: [rowIdx, colIdx] 
    }); 
    orbject.on("mousedown", this.handleMouseDown); 
    orbject.on("mouseup", this.handleMouseUp); 
    orbject.on("mouseout", this.handleMouseOut); 
    orbject.on("mousemove", this.handleMouseMove); 

    this.orbs[colIdx].push(orbject); 
    } 
} 

这已使拖放的好处在之前的地方速度要快得多,速度非常缓慢,但我仍然无法让我的物体交换位置。

要清楚,我的主要问题是知道我应该改变哪些x,y值。在handleMouseMove的那一刻,我一直在努力改变:

e.target.attrs.x = newX; 
e.target.attrs.y = newY; 
// newX and newY can be any number 

但是,不管是什么我将其更改为,它没有任何效果。所以它会帮助我知道是否改变了错误的东西/地方,例如,也许我应该从我存储的数组中改变Kinetic Circle?再次感谢。

编辑2:

我想我明白了!但是,我不得不采取this.orbswindow.orbs设置窗口,并测试它,我做的事:

window.orbs[0][0].x(450); 
window.orbs[0][0].draw(); 

而这引起了x位置改变。但把它放在窗口里似乎不是很好的做法?

编辑3:

我拿到了宝珠到现在不断交换,除了当它是相同的天体被再次交换而mouseover继续射击。然而,在mouseup,它可以再次交换。我还必须再次设置多个图层以使mouseover事件在另一个球体上工作,但是性能似乎有所提高。

我要去尝试,并找出如何让他们能够在相同的鼠标保持不断交换,但在此期间,这里是我写来实现这一代码:

addRow (colIdx) { 
    for (let rowIdx = 0; rowIdx < 6; rowIdx++) { 

    // same code as before, changed attr given to Kinetic.Circle 

    let orbject = new Kinetic.Circle({ 
     x: (rowIdx + 0.5) * 100, y: (colIdx + 0.5) * 100, 
     width: 100, height: 100, 
     fill: orbColor, draggable: true, orbId: `orb${colIdx}${rowIdx}` 
    }); 
    } 
} 

handleMouseDown (e) { 
    window.currentOrb = window.orbs[e.target.attrs.orbId]; 
    window.newX = e.target.attrs.x; 
    window.newY = e.target.attrs.y; 
} 

鼠标下降ID和其X和Y

handleMouseUp (e) { 
    window.currentOrb.x(window.newX); 
    window.currentOrb.y(window.newY); 
    window.currentOrb.parent.clear(); 
    window.currentOrb.parent.draw(); 
    window.currentOrb.draw(); 
    window.currentOrb = undefined; 
    for (let i = 0; i < 5; i++) { 
    for (let j = 0; j < 6; j++) { 
     window.orbs[`orb${i}${j}`].draw(); 
    } 
    } 
} 

当鼠标被释放,目前,所有的球体是重新绘制,使他们都可以用来保存currentOrb。我打算对此进行重构,以便只有天体才会有这种变化。

handleMouseMove (e) { 

    if (window.currentOrb !== undefined && (window.currentOrb.attrs.orbId !== e.target.attrs.orbId)) { 
    window.orbMove.pause(); 
    window.currentTime = 0; 
    window.orbMove.play(); 
    let targOrbX = e.target.attrs.x; 
    let targOrbY = e.target.attrs.y; 
    // This is the target orb that's being changed's value 
    // We're storing this in targOrb 

    e.target.x(window.newX); 
    e.target.y(window.newY); 
    e.target.parent.clear(); 
    e.target.parent.draw(); 
    e.target.draw(); 

    // Here we have the previously set current orb's position becoming 
    // the target orb's position 

    window.newX = targOrbX; 
    window.newY = targOrbY; 

    // Now that the move is made, we can set the newX and Y to be the 
    // target orb's position once mouseup 
    } 
} 

宝珠交换逻辑,其适用于在经过球体一次,但如果它们再次越过在同一回合。

回答

0

什么时候“悬停”正式发生?

  • 当鼠标事件的位置进入第二个圆球?如果是的话,打测试鼠标VS每个非拖动球体:

    // pseudo-code -- make this test for every non-dragging orb 
    var dx=mouseX-orb[n].x; 
    var dy=mouseY-orb[n].y; 
    if(dx*dx+dy*dy<orb[n].radius){ 
        // change orb[n]'s x,y to the dragging orb's x,y (and optionally re-render) 
    } 
    
  • 当拖动球体相交的第二天体?如果是的话,碰撞测试拖动球体VS每个非拖动球体:

    // pseudo-code -- make this test for every non-dragging orb 
    var dx=orb[draggingIndex].x-orb[n].x; 
    var dy=orb[draggingIndex].y-orb[n].y; 
    var rSum=orb[draggingIndex].radius+orb[n].radius; 
    if(dx*dx+dy*dy<=rSum*rSum){ 
        // change orb[n]'s x,y to the dragging orb's x,y (and optionally re-render) 
    } 
    

顺便说一句,如果你拖动一个天体的所有其他天体,其他天体将所有堆栈上的拖动球体原来的位置 - - 那是你要的吗?

+0

我想要什么(暂时 - 我只是想至少让orb交换工作)是前者。我对代码进行了一些更改,奖金是拖放速度更快,但交换仍然无效。我的主要问题是如何让球体进行交换,以及哪些x,y我改变了。我会更改我的操作和更详细的地址,我想在上面。谢谢。 – karivool

+0

自从我使用K-JS之后已经有一段时间了,在拖动轨道上应该有一个像onDragMove事件。这给你拖动的位置。不要打扰使用内置的“相交”方法 - 速度很慢。相反,使用我在答案中列出的两种方法之一。请记住,使用K-JS,您必须重新绘制图层,以便让悬停的球体可视化移动到已保存的x,y。如果你的球体没有移动,在移动每个球体后,确保你正在做类似layer.redraw的事情。 – markE

+1

谢谢,当鼠标接触到一个(并且可以连续交换它们)时,我已经设法让我的球体交换位置。当'mousemove'仍然在触发时,当你试图交换时,它不会这样做,所以我会解决这个问题。 '.draw'似乎不适用于'mousemove',但它适用于'mouseup',但我会尽力解决这个问题。再次感谢! – karivool