JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://threedubmedia.com/inc/js/jquery.event.drag-2.2.js"></script>
<div style="width: 100%;
height: 55px;"></div>


<div data-drag="0" class="thing">
  <div class="circle"></div>
</div>
  <div class="magnet-zone">
  <div class="magnet"></div>
</div>

CSS

.thing, .thing .circle, .magnet {
  border-radius: 50%;
  width: 60px;
  height: 60px;
}

.thing .circle, .magnet-zone {
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
  -webkit-perspective: 1000;
          perspective: 1000;
  -webkit-transform: translate3d(0, 0, 0);
          transform: translate3d(0, 0, 0);
}

.explain {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
          transform: translateY(-50%);
}

html {
  height: 100%;
}

body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  text-align: center;
  font-family: 'Open Sans', 'Lato', 'Helvetica Neue', Arial, sans-serif;
}

* {
  -webkit-tap-highlight-color: transparent;
  -webkit-tap-highlight-color: transparent;
  /* For some Androids */
}

.thing {
  position: absolute;
  -webkit-transform: translate(0, 0);
      -ms-transform: translate(0, 0);
          transform: translate(0, 0);
  margin: 0px;
  cursor: pointer;
}
.thing .circle {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: #888;
  background-image: url(http://gravatar.com/avatar/84eac3a27d1acf0ef0d835d92c999b0d?s=80);
  background-size: contain;
  background-repeat: no-repeat;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  -webkit-transform: scale(1);
      -ms-transform: scale(1);
          transform: scale(1);
  -webkit-transition: -webkit-transform 50ms linear;
          transition: transform 50ms linear;
}
.thing.transition {
  -webkit-transition: -webkit-transform 150ms cubic-bezier(0.175, 0.885, 0.145, 1.25);
          transition: transform 150ms cubic-bezier(0.175, 0.885, 0.145, 1.25);
}
.thing.edge {
  -webkit-transition: all 400ms cubic-bezier(0.175, 0.885, 0.345, 1.1);
          transition: all 400ms cubic-bezier(0.175, 0.885, 0.345, 1.1);
}

.magnet-zone {
  pointer-events: none;
  -webkit-transition: -webkit-transform 300ms cubic-bezier(0.175, 0.885, 0.145, 1.32);
         ...

JavaScript

var magnet = document.querySelector('.magnet-zone');
function isOverlapping(el1, el2) {
    var rect1 = el1.getBoundingClientRect(), rect2 = el2.getBoundingClientRect();
    return !(rect1.top > rect2.bottom || rect1.right < rect2.left || rect1.bottom < rect2.top || rect1.left > rect2.right);
}
function moveToPos(x, y, here) {
    here.style.transform = 'translate(' + Math.round(x, 10) + 'px, ' + Math.round(y, 10) + 'px) translateZ(0)';
    here.style.webkitTransform = 'translate(' + Math.round(x, 10) + 'px, ' + Math.round(y, 10) + 'px) translateZ(0)';
}
function moveMagnet(x, y) {
    var dist = 12, width = $('body').width() / 2, height = $('body').height(), direction = x > width ? 1 : -1, percX = x > width ? (x - width) / width : -(width - x) / width, percY = Math.min(1, (height - y) / (height / 2));
    magnet.style.marginLeft = Math.round(dist / 1.5 * percX) + 'px';
    magnet.style.marginBottom = Math.round(dist * percY) + 'px';
}
function move(event) {
    var el = this, magnetRect = magnet.getBoundingClientRect(), elRect = el.getBoundingClientRect();
    x = this._posOrigin.x + event.pageX - this._touchOrigin.x;
    y = this._posOrigin.y + event.pageY - this._touchOrigin.y;
    moveMagnet(x + elRect.width / 2, y + elRect.height / 2);
    $('body').addClass('moving');
    var touchPos = {
        top: y,
        right: x + elRect.width,
        bottom: y + elRect.height,
        left: x
    };
    overlapping = !(touchPos.top > magnetRect.bottom || touchPos.right < magnetRect.left || touchPos.bottom < magnetRect.top || touchPos.left > magnetRect.right);
    if (overlapping) {
        var mx = magnetRect.width / 2 + magnetRect.left;
        var my = magnetRect.height / 2 + magnetRect.top;
        x = mx - elRect.width / 2;
        y = my - elRect.height / 2;
        if (!$(el).hasClass('overlap')) {
            $(el).addClass('transition');
            setTimeout(function () {
                $(el).removeClass('transition');
            }, 150);
           ...