JSFiddle - React, Tailwind, and code Playground
by thmsdnnr
HTML
<div class="container">
<div class="items" id="itemContainer">
<div class="item item1">ITEM 1</div>
<div class="item item2">ITEM 2</div>
<div class="item item3">ITEM 3</div>
<div class="item item4">ITEM 4</div>
</div>
<div class="info">
</div>
</div>
</div>
CSS
div.contanier {
margin: 10px;
}
div.info {
display: absolute;
left: 250px;
}
div.items {
padding: 5px;
width: 500px;
margin: auto;
display: flex;
flex-wrap: row wrap;
}
div.item {
width: 100px;
height: 100px;
position: absolute;
display: inline-block;
background-color: rgba(255, 0, 0, 0.5);
}
.item1 {
top: 100px;
left: 100px;
}
.item2 {
top: 140px;
left: 140px;
}
.item3 {
top: 160px;
left: 160px;
}
.item4 {
top: 180px;
left: 180px;
}
JavaScript
let mouseDown = false;
let overlap = false;
let divs = document.querySelectorAll('div.item');
let container = document.querySelector('div.container');
divs.forEach((d) => d.addEventListener('mousedown', down));
divs.forEach((d) => d.addEventListener('mouseup', function() {
mouseDown = false;
}));
divs.forEach((d) => d.addEventListener('mouseleave', function() {
mouseDown = false;
}));
function down(e) {
if (e.target.id === 'itemContainer') {
return;
}
e.stopPropagation();
mouseDown = true;
}
container.addEventListener('mousemove', mouseMove);
function mouseMove(e) {
if (!mouseDown) {
return;
}
let coords = e.target.getBoundingClientRect();
let movX = e.movementX;
let movY = e.movementY;
if (!collision(movX, movY, e.target.classList[1], coords)) {
e.target.style.left = `${coords.left+movX}px`;
e.target.style.top = `${coords.top+movY}px`;
}
}
function collision(newX, newY, movingPart, movingRect) {
let takenPositions = []; //array of arrays of rects' L, R, Top, Bottom coords
let newCoords = {
id: movingPart,
left: movingRect.left + newX,
right: movingRect.right + newX,
bottom: movingRect.bottom + newY,
top: movingRect.top + newY
};
let collision = false;
divs.forEach((d) => {
if (d.classList[1] !== movingPart) { // a thing can't collide with itself
let c = d.getBoundingClientRect();
takenPositions.push({
id: d.classList[1],
left: c.left,
right: c.right,
top: c.top,
bottom: c.bottom
});
}
});
takenPositions.forEach((p) => {
//if new bottom hits existing top
//or new top is hits existing bottom
//is it the case that they aren't side by side but actually colliding?
if ((newCoords.bottom == p.top) && ((newCoords.right > p.left) || (newCoords.left < p.right))) {
collision = true;
...