JSFiddle - React, Tailwind, and code Playground

by Martin Parenteau

HTML

<script src="//cdn.jsdelivr.net/interact.js/1.2.6/interact.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<div class="container">

  <div id="div1" data-x="20" data-y="20" class="draggable ui-widget-content">
    <p>Default (snap: true), snaps to all other draggable elements</p>
  </div>

  <div id="div2" data-x="120" data-y="140" class="draggable ui-widget-content">
    <p>Default (snap: true), snaps to other elements</p>
  </div>

  <div id="div3" data-x="300" data-y="60" class="draggable ui-widget-content">
    <p>Default (snap: true), snaps to all other draggable elements</p>
  </div>
</div>

<div>
  <p id="position">
    Position
  </p>
</div>

CSS

.draggable {
  position: absolute;
  width: 90px;
  height: 80px;
  padding: 5px;
  float: left;
  margin: 0 10px 10px 0;
  font-size: .9em;
}

#div1 {
  width: 200px;
  height: 150px;
}

#div2 {
  width: 150px;
  height: 60px;
}

#div3 {
  width: 90px;
  height: 90px;
}

.ui-widget-content p {
  margin: 0;
}

.ui-widget-content {
  border: 1px solid #aaaaaa;
  background-color: #ffffff;
  color: #222222;
}

.container {
  background-color: #FF0000;
  position: relative;
  width: 800px;
  height: 900px;
}

JavaScript

var AXIS_RANGE = 12;
var CORNER_RANGE = 14;
var CORNER_EXCLUDE_AXIS = 8;
var AXIS_EXTRA_RANGE = -6;

var myItems = [];
var currentElement = null;
var offX1, offY1, offX2, offY2;

function getPosition(element) {
  return {
    x: parseFloat(element.getAttribute('data-x')) || 0,
    y: parseFloat(element.getAttribute('data-y')) || 0
  };
}

function isBetween(value, min, length) {
  return min - AXIS_EXTRA_RANGE < value && value < (min + length) + AXIS_EXTRA_RANGE;
}

function getDistance(value1, value2) {
  return Math.abs(value1 - value2);
}

function getSnapCoords(element, axis) {
  var result = {
    isOK: false
  };
  if (currentElement && currentElement !== element) {
    var pos = getPosition(element);
    var cur = getPosition(currentElement);
    var distX1a = getDistance(pos.x, cur.x);
    var distX1b = getDistance(pos.x, cur.x + currentElement.offsetWidth);
    var distX2a = getDistance(pos.x + element.offsetWidth, cur.x);
    var distX2b = getDistance(pos.x + element.offsetWidth, cur.x + currentElement.offsetWidth);
    var distY1a = getDistance(pos.y, cur.y);
    var distY1b = getDistance(pos.y, cur.y + currentElement.offsetHeight);
    var distY2a = getDistance(pos.y + element.offsetHeight, cur.y);
    var distY2b = getDistance(pos.y + element.offsetHeight, cur.y + currentElement.offsetHeight);
    var distXa = Math.min(distX1a, distX2a);
    var distXb = Math.min(distX1b, distX2b);
    var distYa = Math.min(distY1a, distY2a);
    var distYb = Math.min(distY1b, distY2b);
    if (distXa < distXb) {
      result.offX = offX1;
    } else {
      result.offX = offX2
    }
    if (distYa < distYb) {
      result.offY = offY1;
    } else {
      result.offY = offY2
    }
    var distX1 = Math.min(distX1a, distX1b);
    var distX2 = Math.min(distX2a, distX2b);
    var distY1 = Math.min(distY1a, distY1b);
    var distY2 = Math.min(distY2a, distY2b);
    var distX = Math.min(distX1, distX2);
    var distY = Math.min(distY1, distY2);
    var dist =...