Home>
How can I drag an element without shifting just by event.clientX and event.clientY? Can you do it?

When making an element follow the mouse cursor in the mousemove event, if only event.clientX and event.clientY are set in the element's style.left and style.top, the upper left of the element will be the cursor coordinates.

I think you'll use event.offsetX and event.offsetY in the mousedown event, or event.pageX and event.pageY and the element's getBoundingClientRect () to subtract the coordinates in the element.

impetusThe package seems to use only event.clientX and event.clientY, but why doesn't it shift to the upper left of the element? How are you doing

official demo page of impetus
  • http://chrisbateman.github.io/impetus/
source of impetus (corresponding part (probably part))
  • https://github.com/chrisbateman/impetus/blob/master/src/Impetus.js#L186-L242
  • https://github.com/chrisbateman/impetus/blob/master/docs/index.htm#L209-L212
Code for comparison
<! DOCTYPE html>
<html>
<head>
  <meta charset = "utf-8">
  <title></title>
  <style>
.draggable {
  width: 50px;
  height: 50px;
  position: absolute;
  left: 0;
  top: 0;
}
.draggable :: before {
  content: attr (id);
}
#good {
  background: lime;
}
#bad {
  background: red;
}
#impetus {
  background: blue;
}
  </style>
</head>
<body>
     
     
     
  <script src = "https://unpkg.com/impetus"></script>
  <script>
// good
document.getElementById ('good'). addEventListener ('mousedown', ({offsetX, offsetY, pageX, pageY, target}) =>{
  if (offsetX === void 0 || offsetY === void 0) {
    const {left, top} = target.getBoundingClientRect ()
    offsetX = pageX --left
    offsetY = pageY --top
  }
  const mousemove = e =>{
    e.preventDefault ()
    target.style.left = e.clientX --offsetX +'px'
    target.style.top = e.clientY --offsetY +'px'
  }
  const mouseup = e =>{
    document.removeEventListener ('mousemove', mousemove)
    document.removeEventListener ('mouseup', mouseup)
  }
  document.addEventListener ('mousemove', mousemove)
  document.addEventListener ('mouseup', mouseup)
})
// bad // only clientX, clientY
document.getElementById ('bad'). addEventListener ('mousedown', ({target}) =>{
  const mousemove = e =>{
    e.preventDefault ()
    target.style.left = e.clientX +'px'
    target.style.top = e.clientY +'px'
  }
  const mouseup = e =>{
    document.removeEventListener ('mousemove', mousemove)
    document.removeEventListener ('mouseup', mouseup)
  }
  document.addEventListener ('mousemove', mousemove)
  document.addEventListener ('mouseup', mouseup)
})
// impetus
new Impetus ({
  source: document.getElementById ('impetus'),
  update (x, y) {
    this.style.left = x +'px'
    this.style.top = y +'px'
  }
})
  </script>
</body>
</html>


Demo page of "Code for comparison" above

How can I rewrite "bad" in the "comparison code" so that the element can follow the mouse cursor without shifting only with event.clientX and event.clientY?

  • Answer # 1

    The idea is that the amount of movement of the mouse is the same as that of the target object.left,topI think you should change.

    Impetus seems to be like that.
    https://github.com/chrisbateman/impetus/blob/master/src/Impetus.js#L291-L292

    How can I rewrite "bad" so that the element can follow the mouse cursor without shifting only with event.clientX and event.clientY?

    I'm in trouble if I say "only event.clientX and event.clientY"
    e.movementXOre.movementYYou can see the amount of movement by looking at it,
    ↓ I think you can do something like this.

    var mousemove = function (e) {
      e.preventDefault ()
      target.style.left = parseInt (target.style.left || '0') + e.movementX +'px';
      target.style.top = parseInt (target.style.top || '0') + e.movementY +'px';
    }

    *leftOrtopThe initial value ofpxIt is assumed that it is specified in units or has no initial value.