From dP = dM To dragging any element
Published: 2023-11-07 23:46:41

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 :

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

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

```
We then have :

```js

posTargetFinal-posTargetInitial = posMouseFinal - posMouseInitial

```

The final position of the target element is given by:

```js

posTargetFinal = posMouseFinal-(posMouseInitial-posTargetInitial)

``` 

Here is the implementation in pure JS :

```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");
```
You can test it here : [DemoDrag](https://flems.io/#0=N4IgtglgJlA2CmIBcBWFA6ATARgDQgDMIEBnZAbVADsBDMRJEdACwBcxYR8BjAeytbwByEAB4oEAG4ACaAF4AOiCjwwvJQD4FVadIAqAUQDKe7aID0EyVqrauIEvATdWEfmUYAGJNgDMIAF9cajoGJgArMh5+QWFGbQIAVyoXNx0wGgBreAARACcaAHNCmgAjBGkAClYaPML4VgBKaWBtbV0+KhJWfWk5aShebkT6AXR61gMEUdYAIQBPAEkoatqJxoBudultvXRuWBoSEgAZCG70GhhKpRU1JU22nWkEHvOABzz4Y-goPukCDRYI4trZnp1utJ3rwIAJ-pUAB7-Ty4aTzZHNOQaKrABGo+YBR7PbYQnoSAgEeHvTCo97YTHYyqtZ66JFIKGYdBIgC0UOwXNw2106PZ1PQ6N5dPF20JT10ryhvBIejWDR2LP+0JIAFleIlHOrdLp+lrdfr4IsqBAekLNUqVXUGpbrYajSaYQJKkTtkkUq5+NJmDQqHB4GbHDleAB3HSVeDNZlG6TwdCfeCSISsHLwQGJWCsL2gpMfL4-P79Vh5RLwDau3SmvWOZ09d2wgspg4QTMADVRHdgXYEAE0iUmtQ6Js27W3KnteBTHKwTjnWKi5wuGnpeO9R9IAnKAclUgGgyGEOH4ABVd5VeMtW0l76OcsAoEg217brzBDoUo0biZIUeR6iG-xKOU1ZKEWe4Hr6x46KeoYXrqGa3gmD6UpUACEj5ls0XysIkeRUNB9ZKhe-y4tI7L9oOrC9mi1HJvsA6ZkOASkdI5jmIqyqqi2vEUbylQNuaU6Sva-HNo0trjvx-zkgQInkY28Coopyk6qpza0pJjqsNJMkap+rDfvA-wAAZ-gBQEgVASBfFAGwIAQrBIAAJMAcn6VyATvAiGysNuHnALxE4NOKfkIhZMoHnsVxQAYGYCGc3RCPAeQ3OAqmDDGSiooh56qZGMaooCwLxtB2zmAAVNVPEAArAeUqjSFGzBCNIaiSLChTSEFvCvt0uyXDASWZqlsQZVlajmok7z5YGwZIap15lW+lUjQl40pecU2ZUos2ON18CLYVYaqShamvhVu41eY2zbIMwwzKNiXJUue3pQd2VzQtXBLWeF3mmtN2OLuz0jJmb07Z9aVUNNh2qSdZ3LUV5pXett1VVQ+5ghk2T5EUJQtVldzqCA3pgnY+COM4-pdCIKAAGxIJ43LeJ4gTBCAtD0CI+zHPYnSxKwIilLwUDoomXVrLC7KeKCePaOg5P3s8UbQKwzDsgALJ4nj+dBHUQIUbB6wbRvbNZgHAck9nSBBNYkkRJC8HkSAndBWrWmkSBEAivxK-YdPwPBHggLrqCBAAugEQA)

That was the theory, but in practice :

```js

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");

```
You can test it here : [Demo](https://flems.io/#0=N4IgtglgJlA2CmIBcAWArAOgEwEYA0IAxgPYB2AzsQskVbAIYAO58UIBAZhAucgNqhS9MIiQgMACwAuYWO1qkp8RTQA8UCADcABOSkBPBAF4AOiABGxAE5R4VpFkYAPXVWjarrANyNi5CFIQZEieDIGa8F5SxIwOAAxxzl4IHFLxiU5m2tCmIADuVkxmXtoAfCak2trqWtlQubZgxGblldoAKgCiAMrtFaoA9Bqapdr9w3W5jPSk8C0V-UNarYPDrQuk8iwIhIFkvGJxSADsOCAAvniCwqLiAFa8BCSKylI0FRwArqS7QZVg9AA1vAACKFADm4Po5gQ2gAFFJ6FZwfApABKbTADZVZ56DraIzaKDEQifESKDAoqSdBDkqQAIX0AEkoAikVS0V4Kjj9lJtABhAlEklk16U1E0+B0xksuFmaazMyc7naXF8gDqQuFpLp4uptNeMtZZgKRRAnLGlRV7QwhAY5HIABkIHoMPQYHKQI1muauaQVQg+S7GJ4HawhRx6LAWCVsdovj89pUJDM4PAALLET4sEHEPKVOHwDHAS1VKrwDAh+ARRQg+CRz6wKRw5VtKrB0MsKBCqRWT6RUvac5xhO-MjaFOkNOZ7PwACqjHhRcxg-b5CrYe7hMj0ciKqqNr0hgr5nohEB4KsWanQrMMP7xRVw-9bVHSYnqYQM5YmYiS+L+7ZBw8IAIQdvAm4Yp4UifFYpB+mWqq8tovYzOQHDWGAQoAAaoRQYTwHKbaIdoAAkwAVnaECvAAGtoAC02jqrasDUYo6rQFIEgDFgDFMRgxAcBwLBSI69ZSOczh4IBiHkZRrGvAAmnxNpUa8AAS8AQOC0g8XxzGCcJqLtDEkmZMRaLYYBzFHggGB4ehmE9oUFAYVYYAIUOcY2u6UCdDWokukosxWJ6TSzsS+ZmHgH5Tl+WY5nmpAxTuLCtlUxI6mKvn+a8zp6ModhhQl8CfIw0WxdOJULilUZpZ5mWihSOUBflwVFWY4UsE0EQVZOVWzr+8C1bu6WWs+FQAsCYL0JC0IIJ63pKn6GwVFs8A7EmBwgAAzMcSBxPRRxxBcVwgEIIg0LaDryM8wVvGIlhQPomIqgCyIQKQSDaHEfrPgAxKai5Ym0eScRIqAJEkKoSFpOlpDtKAZH9FQYN6r2g+D31I8jMNw9I2O420p7npe15QN9957m0pJWJQ9g9dTVS+P4SZIFwTjeCqJCwNYSB5BIARM9orGzPRsPaQTSPQ20ShOFI9FRtpX2EK8dixlapATaQ-0KvAGNVCTF5Xt8FOIvBKoswEfwhBt9DhML0SxNLTieWDUBcZDRNVBL8NIDtUOuxU5zrZtfzbWgSA4GgFwALrnEAA)