Search code examples
javascriptcssmouseeventdraggable

On each mousemove, the draggable element positioning is getting reset to zero


I'm working on a component that moves a parts diagram around in a container. Right now everything works great on the first mousemove, but on the second the positioning styles are getting reset to zero.

I re-wrote the code outside of Vue and also made a codepen for your viewing.

Codepen: https://codepen.io/paytonburd/pen/WKqEjo

Code:

let diagram = document.getElementById('diagram')
let diagramImg = document.getElementById('diagram-image')
let startX;
let startY;
let walkX;
let walkY;
let dragging = false;

diagram.addEventListener('mousedown', (e) => {
  dragging = true;
  startX = e.pageX - diagram.offsetLeft;
  startY = e.pageY - diagram.offsetTop;
})

diagram.addEventListener('mousemove', (e) => {
  if (!dragging) return;
  e.preventDefault();
  let x = e.pageX - diagram.offsetLeft;
  let y = e.pageY - diagram.offsetTop;

  walkX = x - startX
  walkY = y - startY
  console.log(walkX, walkY)

  diagramImg.style.top = walkY + 'px'
  diagramImg.style.left = walkX + 'px'
})

diagram.addEventListener('mouseleave', () => {
  dragging = false;
})

diagram.addEventListener('mouseup', () => {
  dragging = false;
})

Solution

  • When you mouse down, you always set the startX and startY relative to the position of the diagram, which is always at 0, 0 and never moves.

    I think what you want is to instead set them to relative to the current position of the diagram image instead:

    let diagram = document.getElementById('diagram')
    let diagramImg = document.getElementById('diagram-image')
    let startX;
    let startY;
    let walkX;
    let walkY;
    let dragging = false;
    
    diagram.addEventListener('mousedown', (e) => {
      dragging = true;
      //This is where it went wrong
      startX = e.pageX - diagramImg.offsetLeft; 
      startY = e.pageY - diagramImg.offsetTop; 
    })
    
    diagram.addEventListener('mousemove', (e) => {
      if (!dragging) return;
      e.preventDefault();
      let x = e.pageX - diagram.offsetLeft;
      let y = e.pageY - diagram.offsetTop;
    
      walkX = x - startX
      walkY = y - startY
      console.log(walkX, walkY)
    
      diagramImg.style.top = walkY + 'px'
      diagramImg.style.left = walkX + 'px'
    })
    
    diagram.addEventListener('mouseleave', () => {
      dragging = false;
    })
    
    diagram.addEventListener('mouseup', () => {
      dragging = false;
    })
    

    https://codepen.io/anon/pen/yqdzyq?editors=1111