javascriptcsskeyboardpositionkeycode

Dynamically moving element position using Javascript


This is the code that's causing me issues:

const moveBlock=()=> {
  let x=myBlock.offsetLeft;
  let y=myBlock.offsetTop;
  keyArray.forEach(key=> {
    if (key==='ArrowRight') {
      myBlock.style.left=`${x+50}px`
    } else if (key==='ArrowLeft') {
      myBlock.style.left=`${x-50}px`
    } else if (key==='ArrowDown') {
      myBlock.style.top=`${y+50}px`
    } else if (key==='ArrowUp') {
      myBlock.style.top=`${y-50}px`
    }
  })
}

I'll briefly explain my program:

The program will start you pressing left, right, up, or down--those commands appear as a list at the top of the document. Then you'll press enter

When enter is pressed, the program goes through the array of keyboard directions and the block moves in the specified direction depending on the command in the array. There's a condition for each arrow direction to move the block 50px which way. This is a sequence so we're supposed to see happening.

However, the block only move 50px right or left, etc only once. Why is that? Am I not iterating my x and y variables correctly?


Solution

  • You have to calculate the value of x and y again after moving once. Because when you are moving the block from second time, you are just using original value of x and y computed before the for loop began.

    Add this in your forEach() method.

     x = myBlock.offsetLeft;
     y = myBlock.offsetTop; 
    

    You have later mentioned in the comments about having a delay between each move. You can do that by creating another animate block function, having a timeout within a loop and and calling that animate block function in the timeout.

    const animateBlock = (key)=> {
        let x = myBlock.offsetLeft;
        let y = myBlock.offsetTop;
    
        if (key === 'ArrowRight') {
          myBlock.style.left = `${x + 50}px`
        } else if (key === 'ArrowLeft') {
          myBlock.style.left = `${x - 50}px`
        } else if (key === 'ArrowDown') {
          myBlock.style.top = `${y + 50}px`
        } else if (key === 'ArrowUp') {
          myBlock.style.top = `${y - 50}px`
        }
    }
    
    
    const moveBlock = () => { 
      keyArray.forEach((key, i) => {
         setTimeout(() => {
           animateBlock(key);
         }, i * 1000);
      })
    }
    

    Working demo: https://codepen.io/nikhilmopidevi/pen/gOYjgYd