JSFiddle - React, Tailwind, and code Playground

by frumbert

HTML

<script src="https://unpkg.com/plain-draggable"></script>
<ol>
<li>Drag the blue or green circle onto a red square to make it stick to it</li>
<li>Now, resize the browser horizontally or vertically</li>
</ol>

<div class="outer">

  <div class="drag blue">
  
  </div>

  <div class="drag green">
  
  </div>

  <div class="snap one">
  
  </div>

  <div class="snap two">
  
  </div>


</div>

CSS

.outer {
  margin: 1rem auto;
  width: 50vw;
  height: 25vh;
  border:1px solid indigo;
  position: relative;
}
.outer>div {
  position: absolute;
}

.snap {
  width: 1rem;
  height: 1rem;
  background-color: red;
  z-index: 1;
}
.one {
  top: 50%;
  right: 45%;
}
.two {
  bottom: 55%;
  left: 55%;
}

.drag {
  bottom: 1rem;
  left: 1rem;
  width: 1rem;
  height: 1rem;
  z-index: 2;
  border-radius: 50px;
  background-color: rgba(0,0,255,.5);
}
.drag.green {
  background-color: rgba(0,224,0,.5);
  bottom: 40%;
}

JavaScript

let snapped = false, grab;
const tolerance = 20;
const drags = document.querySelectorAll(".drag");
const snaps = document.querySelectorAll(".snap");

Array.from(drags).map(function(el) {
  const d = new PlainDraggable(el, {
    onMove: function(el) {
      snapped = !!el.snapped;
    },
    onDragStart: function (obj) {
      grab = obj;
    },
    onDragEnd: function (newPosition) {
    const bb = this.containment.getBoundingClientRect();
    var dropped = this.snap.targets.find(function(bound) {
			const target = bound.boundingBox;
      const xpos = newPosition.left - bb.x;
      const ypos = newPosition.top - bb.y;
      console.dir(target);
return (Math.abs(target.x - xpos) < tolerance) && (Math.abs(target.y - ypos) < tolerance);
    });

console.dir(dropped);

	if (!snapped) {
        grab.target.style.transform = 'none';
        this.position(); // future-proof consecutive drags
      }
      grab = undefined;
    },
    snap: {
      targets: Array.from(snaps)
    },
    containment: document.querySelector("outer")
  });
});