Vanilla javascript draggable div within parent

Viewed 2542

I want to achieve a draggable element in vanilla javascript. I want to make a small circular div draggable within a square div.

To make myself a bit more clear, I do NOT want to:

  • Create drag and drop,
  • Use jQuery UI or any other library or plugin to achieve this, just vanilla javascript

I already have a few events for handling dragging:

parent.addEventListener("mousedown", ..),
document.addEventListener("mouseup", ..) and
document.addEventListener("mousemove", ..)

My question is how can I keep the draggable inside the given bounds of its parent?

Reference: https://codepen.io/ChickenFlavored/pen/rNxRXGo

2 Answers

You may use getBoundingClientRect that gives DOMRect object(an invincible rectangle that encompass the object) with eight properties: left, top, right, bottom, x, y, width, height.

var parent = document.querySelector('.parent');
var parentRect = parent.getBoundingClientRect();

var draggable = document.querySelector('.draggable');
var draggableRect = draggable.getBoundingClientRect();

You can get the mouse (X,Y) coordinates anytime by using e.clientX and e.clientY, so just check if they are outside the bounding rectable of .parent div if so then only update the draggable div's left and top properties

if( (e.clientX >= parentRect.left && (e.clientX+draggableRect.width <= parentRect.right)) &&
    (e.clientY >= parentRect.top && (e.clientY+draggableRect.height <= parentRect.bottom)) 
    //+draggableRect.height and +draggableRect.height accounts for the size of ball itself
){
            draggable.style.left = `${e.clientX}px`;
            draggable.style.top = `${e.clientY}px`;
}

Note that numbers increase down and towards right in graphics world

enter image description here https://codepen.io/vsk/pen/PozVryr

UPDATE: To fix the issue mentioned in comment use this

  if(/* mouse was moved withing red container's bounds*/)
  else{
    //if mouse went out of bounds in Horizontal direction
    if(e.clientX+draggableRect.width >= parentRect.right){
       draggable.style.left = `${parentRect.right-draggableRect.width}px`;
    }
    //if mouse went out of bounds in Vertical direction
    if(e.clientY+draggableRect.height >= parentRect.bottom){
       draggable.style.top = `${parentRect.bottom-draggableRect.height}px`;
    }
  }

And assign mousemove to document insted of the div container

I hope you could provide a code snippet to try to simulate what you want, a codepen url, codesandbox or similar.

I made this sample using what you provided : )

let x = event.clientX - element.offsetLeft
const elementWidth = element.clientWidth
const fullX = x + elementWidth
const containerW = yourContainer.clientWidth
if(fullX > containerW){
  //If element will be out of container
  x = containerW - elementWidth // So it will be never out of container
}
element.style.transform = "translate("+x+"px, "+y+"px)"
Related