Draggable + Resizable Div
by Rajesh Danabal
HTML
<div class="container" id="node-container"></div>
CSS
body { margin: 0; background: #111; height: 100vh; display: flex; justify-content: center; align-items: center; }
.container { position: relative; width: 800px; height: 600px; background: #222; }
.item {
position: absolute;
background: #444;
border: 1px solid #888;
border-radius: 6px;
box-sizing: border-box;
user-select: none;
}
.header { height: 20px; background: #666; cursor: move; }
.resize { position: absolute; width: 5px; height: 5px; background: #aaa; cursor: se-resize; bottom: 0; right: 0; }
JavaScript
const gridSize = 5;
const minW = gridSize,
minH = gridSize;
const container = document.getElementById("node-container");
let items = [];
function snap(v) {
return Math.round(v / gridSize) * gridSize;
}
function overlaps(a, b) {
return !(
a.x + a.w <= b.x ||
a.x >= b.x + b.w ||
a.y + a.h <= b.y ||
a.y >= b.y + b.h
);
}
function createItem(x, y, w, h) {
const el = document.createElement("div");
el.className = "item";
el.style.left = x + "px";
el.style.top = y + "px";
el.style.width = w + "px";
el.style.height = h + "px";
const resizeHandle = document.createElement("div");
resizeHandle.className = "resize";
el.appendChild(resizeHandle);
container.appendChild(el);
const data = { el, x, y, w, h };
items.push(data);
let drag = false,
resize = false;
let startX, startY, startPos;
el.addEventListener("pointerdown", (e) => {
console.log('element mouse down');
drag = true;
startX = e.clientX;
startY = e.clientY;
startPos = { x: data.x, y: data.y };
e.preventDefault();
});
resizeHandle.addEventListener("pointerdown", (e) => {
console.log('resize handler mouse down');
resize = true;
startX = e.clientX;
startY = e.clientY;
startPos = { w: data.w, h: data.h };
e.preventDefault();
e.stopPropagation();
});
window.addEventListener("pointermove", (e) => {
if (drag) {
let nx = snap(startPos.x + (e.clientX - startX));
let ny = snap(startPos.y + (e.clientY - startY));
// collision check
const test = { ...data, x: nx, y: ny };
const collide = items.some((it) => it !== data && overlaps(test, it));
if (!collide) {
data.x = nx;
data.y = ny;
el.style.left = nx + "px";
el.style.top = ny + "px";
}
}
if (resize) {
let nw = snap(startPos.w + (e.clientX - startX));
let nh = snap(startPos.h +...