Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix Div element "jump" on drag?

The dragging works but the bug is that when I drag the element somehow "jumps" and does not flow with the mouse. See it in the code. Don't worry about removing event listeners, I will add them as soon as this works.
I have an issue on a draggable "div" element. I've searched many answers before I posted this question but nothing seems to be the solution(or maybe I am not understanding the problem really well).
Thank you!

const hotspot = document.getElementsByClassName("hotspot")[0];
const container = document.getElementsByClassName("container")[0];
let containerRect = container.getBoundingClientRect();
let hsRect = hotspot.getBoundingClientRect();

let relMouse = { x: 0, y: 0 };
let windowMouse = { x: 0, y: 0 };
let isUserIntercating = false;

const handlePointerUp = (e) => {
  isUserIntercating = false;
};

const handlePointerDown = (e) => {
  isUserIntercating = true;
  hsRect = hotspot.getBoundingClientRect();
  relMouse = { x: e.pageX - hsRect.x, y: e.pageY - hsRect.y };

  window.addEventListener("pointerup", handlePointerUp, false);
};

const handlePointerMove = (e) => {
  hsRect = hotspot.getBoundingClientRect();
  containerRect = container.getBoundingClientRect();
  windowMouse = { x: e.clientX - relMouse.x, y: e.clientY - relMouse.y };
};
const update = (t) => {
  requestAnimationFrame(update);
  if (isUserIntercating) {
    hotspot.style.transform = `translate(${
      windowMouse.x - containerRect.x
    }px,0px)`;
  }
};
update();
hotspot.addEventListener("pointerdown", handlePointerDown, false);
window.addEventListener("pointermove", handlePointerMove, false);
body {
  font-family: sans-serif;
  margin: 0;
}
.container {
  padding: 0;
  margin: 50px;
  max-width: 600px;
  min-height: 600px;
  background-color: blanchedalmond;
}

.hotspot {
  /* position: absolute; */
  background-color: aqua;
  /* transform: translate(100px, 100px); */
  min-height: 100px;
  max-width: 100px;
  z-index: 200;
}
<!DOCTYPE html>
<html>
  <head>
    
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div class="container">
      <div class="hotspot"></div>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>
like image 202
Bogdan - Daniel Mihalcea Avatar asked Feb 04 '26 10:02

Bogdan - Daniel Mihalcea


1 Answers

Try like this:

const hotspot = document.getElementsByClassName("hotspot")[0];
const container = document.getElementsByClassName("container")[0];
let containerRect = container.getBoundingClientRect();
let hsRect = hotspot.getBoundingClientRect();

let relMouse = { x: 0, y: 0 };
let windowMouse = { x: 0, y: 0 };
let isUserIntercating = false;

const handlePointerUp = (e) => {
  isUserIntercating = false;
};

const handlePointerDown = (e) => {
  isUserIntercating = true;
  hsRect = hotspot.getBoundingClientRect();
  relMouse = { x: e.pageX - hsRect.x, y: e.pageY - hsRect.y };

  window.addEventListener("pointerup", handlePointerUp, false);
};

const handlePointerMove = (e) => {
  hsRect = hotspot.getBoundingClientRect();
  containerRect = container.getBoundingClientRect();
  windowMouse = { x: e.clientX - relMouse.x, y: e.clientY - relMouse.y };
  requestAnimationFrame(update);
};
const update = (t) => {
  if (isUserIntercating) {
    hotspot.style.transform = `translate(${
      windowMouse.x - containerRect.x
    }px,0px)`;
  }
};
hotspot.addEventListener("pointerdown", handlePointerDown, false);
window.addEventListener("pointermove", handlePointerMove, false);
body {
  font-family: sans-serif;
  margin: 0;
}
.container {
  padding: 0;
  margin: 50px;
  max-width: 600px;
  min-height: 600px;
  background-color: blanchedalmond;
}

.hotspot {
  /* position: absolute; */
  background-color: aqua;
  /* transform: translate(100px, 100px); */
  min-height: 100px;
  max-width: 100px;
  z-index: 200;
}
<!DOCTYPE html>
<html>
  <head>
    
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div class="container">
      <div class="hotspot"></div>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

The issue seemed to be that the update function kept calling itself all the time, which is not really ideal. The update should only be called in the handlePointerMove function (only change the hotspot position when the mouse moves).

like image 80
sbgib Avatar answered Feb 05 '26 22:02

sbgib



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!