fatt101 fatt101 - 3 months ago 17
jQuery Question

collision detection on more than 2 divs with jQuery draggable?

Here is a fiddle;

http://jsfiddle.net/dh4qysej/

I'm looking to do this with dynamically created elements, so the divs may not actually exist yet when the function is called.

I would like to try work out a solution which could cover x amount of divs and handle it with minimal code, but making a scrappy version to accommodate three divs seems to be the logical first step before figuring out a way to cover even more.

I figured I would have to put if - else if statements in order to detect calculations across all the variables, however it doesn't seem to work. I was hoping someone could point me in the right direction?

Thanks in advance - code below (working between first two divs);



function collision($div1, $div2, $div3) {
if ($div1.length > 0) {
var x1 = $div1.offset().left;
var y1 = $div1.offset().top;
var h1 = $div1.outerHeight(true);
var w1 = $div1.outerWidth(true);
var b1 = y1 + h1;
var r1 = x1 + w1;
}

if ($div2.length > 0) {
var x2 = $div2.offset().left;
var y2 = $div2.offset().top;
var h2 = $div2.outerHeight(true);
var w2 = $div2.outerWidth(true);
var b2 = y2 + h2;
var r2 = x2 + w2;
}

if ($div3.length > 0) {
var x3 = $div3.offset().left;
var y3 = $div3.offset().top;
var h3 = $div3.outerHeight(true);
var w3 = $div3.outerWidth(true);
var b3 = y3 + h3;
var r3 = x3 + w3;
}

if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) {
return false;
} else {
return true;
}
}


onmousemove = function(e) {
$('#result').text(collision($('#div1'), $('#div2'), $("#div3")));
};


$('#div1,#div2, #div3').draggable();

#div1 {
width: 200px;
height: 50px;
background-color: pink;
}
#div2 {
width: 200px;
height: 50px;
background-color: green;
}
#div3 {
width: 200px;
height: 50px;
background-color: red;
}

<strong>Drag divs around.</strong>

<div id="div1">
Div1
</div>
<br/>
<div id="div2">
Div2
</div>
<br>
<div id="div3">
Div3
</div>

<p>Colliding? <span id="result">false</span>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>




Answer
  1. Firstly instead of using id to bind events use class selector.
  2. Use a flag to check if user is currently dragging any of the draggable item.
  3. Loop through all draggable items and test collision with respect to the current dragged element.

function collision(draggableItems) {
  return draggableItems
     .toArray()
    .reduce(function(isColliding, currNode){
        if(isColliding){return isColliding;}
        var $currNode = $(currNode);
        var x1 = $currNode.offset().left;
        var y1 = $currNode.offset().top;
        var h1 = $currNode.outerHeight(true);
        var w1 = $currNode.outerWidth(true);
        var b1 = y1 + h1;
        var r1 = x1 + w1;
        draggableItems.each(function(index, node){
          if(node == currNode || isColliding){
            return;
          }
          var $node = $(node);
          var x2 = $node.offset().left;
          var y2 = $node.offset().top;
          var h2 = $node.outerHeight(true);
          var w2 = $node.outerWidth(true);
          var b2 = y2 + h1;
          var r2 = x2 + w1;
                
          if(!(b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2)){
            isColliding = true;
          }
        });
        return isColliding;
  }, false);
}


    var isDragging = false;

    $('.draggableItem')
      .on('mousedown', function(e){
        isDragging = true;
      })
      .on('mousemove',function(e) {
        if(!isDragging){return;}
        $('#result').text(collision($('.draggableItem')));
      })
      .on('mouseup', function(e){
        isDragging = false;
      });

    $('.draggableItem').draggable();
#div1 {
  width: 200px;
  height: 50px;
  background-color: pink;
}
#div2 {
  width: 200px;
  height: 50px;
  background-color: green;
}
#div3 {
  width: 200px;
  height: 50px;
  background-color: red;
}
<strong>Drag divs around.</strong>

<div id="div1" class="draggableItem">
  Div1
</div>
<br/>
<div id="div2" class="draggableItem">
  Div2
</div>
<br>
<div id="div3" class="draggableItem">
  Div3
</div>

<p>Colliding? <span id="result">false</span>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>

Comments