VladTbk321
VladTbk321

Reputation: 143

How to make element movement more responsive using e.clientX and e.clientY

I am making a microphone element that becomes moveable around the document when the user holds click on it. For this I created this function:

microphoneButton.addEventListener('mousedown', () => {
        mouseIsDown = true;
        window.addEventListener('mousemove', handleMouseMove); 
        // handleMouseMove get's .clientX and .clientY values and store them globally in mousepos
        currMicInterval = setInterval(() => {
            if (mouseIsDown) {
                microphoneButton.setAttribute(
                    'style',
                    `left: ${mousePos.x - 25}px; top: ${mousePos.y - 215}px;`
                );
            }
        }, 100);
    });

Using setInterval is the only method I found that updates the values for x and y that doesn't make my code run an infinite loop. Yet I still get stutterings when I move the mouse too quickly or even when I small steps. How could I fix this?

Upvotes: 0

Views: 371

Answers (1)

kaliatech
kaliatech

Reputation: 17867

Unless you have code elsewhere that you have not shown, every 'mousedown' event is going to create and add yet another mousemove listener. These will accumulate, and so after a few mouse clicks, you are going to be running that code redundantly multiple times on every mouse move. That might be cause of your issue.

Another potential issue is that calling setAttribute for style replaces the style. So you would be overridding any existing style (like a position:absolute?).

It's not clear what your fundamental issue is from your question. See if the snippet below helps. If it does not, I recommend adding more information to your question to show all of your code and what exactly is not working.

const mBtn = document.getElementById('microphoneButton');

let isMouseDown = false;

const handleMouseMove = (evt) => {

  // Note the need to reset the position to absolute because 
  // calling setAttribute will replace existing style:
  //mBtn.setAttribute(
  //  'style',
  //  `position: absolute; left: ${evt.clientX}px; top: ${evt.clientY}px;`
  //);

  // Alternatively, set the properties directly:
  mBtn.style.left = `${evt.clientX - mBtn.offsetWidth/2}px`
  mBtn.style.top = `${evt.clientY - mBtn.offsetHeight/2}px`
}

mBtn.addEventListener('mousedown', () => {
  isMouseDown = true;
  window.addEventListener('mousemove', handleMouseMove);
})

window.addEventListener('mouseup', () => {
  if (isMouseDown) {
    isMouseDown = false;
    window.removeEventListener('mousemove', handleMouseMove);
  }
})
<div>
  <button id="microphoneButton" style="position:absolute">Drag Me</button>
</div>

Upvotes: 1

Related Questions