Ivan Ivan - 3 months ago 21
CSS Question

Drag and drop triangle

I'm new in jquery, so I'm trying to laydown triangle from left to right side so they fit triangle grid. And they can be drop only in right side div. This is so far I got.Tricky is that div looks like triangle but they actually are a square. I have used JqueryUI



$(document).ready(function() {

$(function() {
$(".triangle-1,.triangle-2,.triangle-3,.triangle-4").draggable();
});

$(".up").mouseover(function() {
$(this).css("border-bottom-color", "gray");

});

$(".up").mouseleave(function() {
$(this).css("border-bottom-color", "floralwhite");
});

$(".up").droppable();
});

.container {
width: 1000px;
margin: 0 auto;
background: #ccc;
height: 500px;
}
.left {
background: lightgray;
height: 500px;
}
.triangle-1,
.triangle-2,
.triangle-3,
.triangle-4 {
cursor: pointer;
position: absolute;
z-index: 10;
width: 0;
height: 0;
}
.triangle-1,
.triangle-2 {
border-top: 86px solid green;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}
.triangle-3,
.triangle-4 {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 86px solid red;
}
.up,
.down {
display: inline-block;
width: 0;
height: 0;
position: absolute;
z-index: 0;
}
.up {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 86px solid floralwhite;
left: 50px;
z-index: 0;
}
.down {
border-top: 86px solid floralwhite;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<div class="container">
<div class="row">
<div class="col-xs-6 left">
<div class="triangle-1"></div>
<div class="triangle-2"></div>
<div class="triangle-3"></div>
<div class="triangle-4"></div>
<div class="triangle-1"></div>
<div class="triangle-3"></div>
</div>
<div class="col-xs-6">
<div class="row">
<div class="down" style="left:0">
</div>
<div class="up" style="left:50px">
</div>
<div class="down" style="left:100px">
</div>
<div class="up" style="left:150px">
</div>
<div class="down" style="left:200px">
</div>
<div class="up" style="left:250px">
</div>
<div class="down" style="left:300px">
</div>
<div class="up" style="left:350px">
</div>
<div class="down" style="left:400px">
</div>
</div>
</div>
</div>

</div>




Answer

I've used a function for each of the drop events to correctly position them on drop over the grid. See the doDrop function at the end of the JS and its comments for details on how this works.

$(document).ready(function() {

  $(function() {
    $(".triangle-up,.triangle-down").draggable({});
    $(".down").droppable({
      drop: function(event, ui) {
        
        doDrop(event, ui);
      }
    });
    $(".up").droppable({
      drop: function(event, ui) {
        doDrop(event, ui);
      }
    });
  });

  $(".up").mouseover(function() {
    $(this).css("border-bottom-color", "gray");
  });

  $(".up").mouseleave(function() {
    $(this).css("border-bottom-color", "floralwhite");
  });
});

function doDrop(event, ui) {
  var dropElem = $(event.target);
  var dragElem = ui.draggable;
  var isUp = dragElem.hasClass("triangle-up");
  
  // Check if we're dropping a .triangle-up into a .down
  // or a .triangle-down into a .up
  // If so, we'll choose either the next or previous
  // sibling element to drop to, depending where the
  // mouse is.
  if (isUp && !dropElem.hasClass("up") ||
     !isUp && !dropElem.hasClass("down")) {
    // Get halfway point of drop element
    var dropCentreX = dropElem.offset().left + (dropElem.outerWidth() / 2);

    // Set drop element to next if more than halfway, else to previous
    if (dropCentreX < event.pageX && dropElem.next()) {
      dropElem = dropElem.next();
    } else {
      dropElem = dropElem.prev();
    }
  }

  // Append so positioning is relative to drop element.
  dropElem.append(dragElem);

  // Few positioning calculations
  var width = dropElem.outerWidth();
  var height = dropElem.outerHeight();
  var cntrLeft = (dragElem.outerWidth()/2) - width;
  var cntrTop = (isUp) ? 0 : -height;

  // Position to drag element within the drop element
  dragElem.css({
    left: (cntrLeft) + "px",
    top: (cntrTop) + "px",
    zIndex: "1001"
  });
}
.container {
  width: 1000px;
  margin: 0 auto;
  background: #ccc;
  height: 500px;
}
.left {
  background: lightgray;
  height: 100px;
}
.triangle-down,
.triangle-up {
  cursor: pointer;
  position: absolute;
  z-index: 10;
  width: 0;
  height: 0;
}
.triangle-down {
  border-top: 86px solid green;
  border-right: 50px solid transparent;
  border-left: 50px solid transparent;
}
.triangle-up {
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 86px solid red;
}
.up,
.down {
  display: inline-block;
  width: 0;
  height: 0;
  position: absolute;
  z-index: 0;
}
.up {
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 86px solid floralwhite;
  left: 50px;
  z-index: 0;
}
.down {
  border-top: 86px solid floralwhite;
  border-right: 50px solid transparent;
  border-left: 50px solid transparent;
}
.right-side {
  background-color: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<div class="container">
  <div class="row">
    <div class="col-xs-6 left">
      <div class="triangle-down"></div>
      <div class="triangle-down"></div>
      <div class="triangle-up"></div>
      <div class="triangle-up"></div>
    </div>
    <div class="col-xs-6 right-side">
      <div class="row">
        <div class="down" style="left:0">
        </div>
        <div class="up" style="left:50px">
        </div>
        <div class="down" style="left:100px">
        </div>
        <div class="up" style="left:150px">
        </div>
        <div class="down" style="left:200px">
        </div>
        <div class="up" style="left:250px">
        </div>
        <div class="down" style="left:300px">
        </div>
        <div class="up" style="left:350px">
        </div>
        <div class="down" style="left:400px">
        </div>
      </div>
    </div>
  </div>

</div>

EDIT Correction for > to < in if (dropCentreX < event.pageX && dropElem.next())