DEV Community

artydev
artydev

Posted on

From dP = dM To dragging any element

The previous formula is all you need to drag any element in your html page (in theory at least)

The formula express the fact that if the mouse position varies in a certain quantity then the position of the element being dragged varies in the same quantity, that's all.

Let's assume :

// variation of the position of the element
dP = posTargetFinal - posTargetInitial

// variation of the position of the mouse
dM = posMouseFinal - posMouseInitial

Enter fullscreen mode Exit fullscreen mode

We then have :


posTargetFinal-posTargetInitial = posMouseFinal - posMouseInitial

Enter fullscreen mode Exit fullscreen mode

The final position of the target element is given by:


posTargetFinal = posMouseFinal-(posMouseInitial-posTargetInitial)

Enter fullscreen mode Exit fullscreen mode

Here is the implementation in pure JS :


function makeDraggable (target) {

  const T = document.getElementById(target);

  T.classList.add("demo");

  let ispressed = false;

  const point = (x = 0, y = 0) => ({x, y});

  const diff = (p2, p1) => ({
    x : p2.x - p1.x,
    y : p2.y - p1.y
  })

  let posTarget 
    = posMouse 
    = posMouseInit 
    = posTargetInit 
    = point();

  function handleMouseDown (e) {
    e.preventDefault();
    ispressed = true; 
    posMouseInit = point(e.clientX, e.clientY);
    posTargetInit = point(T.offsetLeft, T.offsetTop);
  }

  function handleMouseUp (e) {
    ispressed = false;
    T.style.background = "blue";
  }

  function handleMouseMove (e) {
    if (!ispressed) return;
    posMouse = {x : e.clientX, y : e.clientY};
    // posTarget = posMouse - (posMouseInit - posTargetInit)
    posTarget = diff(posMouse, diff(posMouseInit, posTargetInit))
    T.style = `background:red;left:${posTarget.x}px;top:${ posTarget.y}px`
  }

  T.addEventListener("mousedown", handleMouseDown, false);

  /*
  // Problem when moving too fast
  T.addEventListener("mouseup", handleMouseUp, false);
  T.addEventListener("mousemove", handleMouseMove, false);
  */

  document.addEventListener("mouseup", handleMouseUp, false);
  document.addEventListener("mousemove", handleMouseMove, false);

}

makeDraggable("demo");
Enter fullscreen mode Exit fullscreen mode

You can test it here : DemoDrag

That was the theory, but in practice :


function makeDraggable (target) {

  const T = document.getElementById(target);
  const C = document.getElementById("pane");
  const W =  document.getElementById("wrap"); 

  T.classList.add("demo");

  let ispressed = false; 

  function handleMouseDown (e) { 
    e.preventDefault();
    ispressed = true; 
  }

  function handleMouseUp (e) { 
    ispressed = false;
    T.style.background = "blue";
  }

  function handleMouseMove (e) {
    if (!ispressed) return;
    const transform = `translate(
        ${e.clientX - W.clientWidth/2 - W.offsetLeft}px,
        ${e.clientY - T.clientHeight/2 - W.offsetTop}px
    )`
    W.style.transform = transform;
  }

  T.addEventListener("mousedown", handleMouseDown, false);
  document.addEventListener("mouseup", handleMouseUp, false);
  document.addEventListener("mousemove", handleMouseMove, false);

}

makeDraggable("demo");

Enter fullscreen mode Exit fullscreen mode

You can test it here : Demo

Top comments (0)