Search code examples
javascriptdraggablecolor-picker

Vanilla javascript draggable div within parent


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


Solution

  • 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