skip to Main Content

i have a ball starting at the upper left corner of a box and when you click on the button then it moves to go to the lower right corner. it stops when it reaches 350px

i want it to go up to the upper right corner after it reaches the lower right corner. but if i copy paste the IfElse statement then the If(pos=350) would run that code right away instead of doing the movement at Else

does that make sense

function animation() {
  let id = null;
  const ball = document.getElementById("ball");   
  let pos = 0;
  id = setInterval(movement, 5);
  
  function movement() {
    if (pos == 350) {
      clearInterval(id);
      ball.style.background =  "green";
      
    } else {
      ball.style.background =  "red";
      pos++; 
      ball.style.top = pos + "px"; 
      ball.style.left = pos + "px"; 
      
    }
    
 
  }
}
#box {
  width: 400px;
  height: 400px;
  margin-top: 20px;
  position: relative;
  background: yellow;
}
#ball {
  width: 50px;
  height: 50px;
  position: absolute;
  background-color: red;
  border-radius:  100%;
}
<button onclick="animation()">Click Here</button>

<div id ="box">
  <div id ="ball"></div>
</div>

2

Answers


  1. The usage of timeout for animation is not ideal. But lets focus on the programming part. Basically I added directionX and directionY for the position increment. Also generalized a little by making a route array for the directions.

    Update: Added colors.

    Update 2: There’s issue with the colors 🙂 They don’t match the animation step. Consider: Using CSS classes instead.

    function animation() {
      let id = null;
      const ball = document.getElementById("ball");
      let posX = 0;
      let posY = 0;
    
      var routes = [{
          dx: 1,
          dy: 1,
          color: "red",
        },
        {
          dx: 0,
          dy: -1,
          color: "green",
        },
        {
          dx: -1,
          dy: 0,
          color: "blue",
        }
      ]
    
      function nextStep(step, posX, posY) {
        if (step == 0 && posX == 350) {
          return 1
        }
        if (step == 1 && posY == 0) {
          return 2
        }
        if (step == 2 && posX == 0) {
          return -1
        }
        return step;
      }
    
      var step = 0
    
      id = setInterval(movement, 5);
    
      function movement() {
    
        step = nextStep(step, posX, posY)
        if (step == -1) {
          clearInterval(id);
          return
        }
    
        var directionX = routes[step].dx
        var directionY = routes[step].dy
    
        ball.style.background = routes[step].color;
        posX += directionX
        posY += directionY
        ball.style.top = posY + "px";
        ball.style.left = posX + "px";
    
      }
    }
    #box {
      width: 400px;
      height: 400px;
      margin-top: 20px;
      position: relative;
      background: yellow;
    }
    
    #ball {
      width: 50px;
      height: 50px;
      position: absolute;
      background-color: red;
      border-radius: 100%;
    }
    <button onclick="animation()">Click Here</button>
    
    <div id="box">
      <div id="ball"></div>
    </div>
    Login or Signup to reply.
  2. Given the code specified, you could set another setInterval when the first animation (the diagonal one) has completed, this time doing nothing with the x position but just decrementing the y position each time and finishing when y becomes 0.

    <style>
      #box {
        width: 400px;
        height: 400px;
        margin-top: 20px;
        position: relative;
        background: yellow;
      }
      
      #ball {
        width: 50px;
        height: 50px;
        position: absolute;
        background-color: red;
        border-radius: 100%;
      }
    </style>
    <button onclick="animation()">Click Here</button>
    
    <div id="box">
      <div id="ball"></div>
    </div>
    <script>
      function animation() {
        let id = null;
        const ball = document.getElementById("ball");
        let pos = 0;
        id = setInterval(movement, 5);
    
        function movement() {
          if (pos == 350) {
            clearInterval(id);
            ball.style.background = "green";
            id = setInterval(movement2, 5);
    
          } else {
            ball.style.background = "red";
            pos++;
            ball.style.top = pos + "px";
            ball.style.left = pos + "px";
    
          }
        }
    
        function movement2() {
          if (pos == 0) {
            clearInterval(id);
          } else {
            pos--;
            ball.style.top = pos + "px";
          }
        }
    
      }
    </script>

    However, note that this is really a rather weird way of doing an animation given CSS has both transform/transition properties and animation with keyframes.

    This matters for any serious animation – for example giving the system the possibility of pushing some of the work onto a graphics processor if the device has one.

    I’d strongly urge you to look into those as your current method is inefficient in terms of usage of processor time (I realise that doesn’t matter for a little exercise like this, but could for example if there was to be a continuous animation) and also it might in the limit not work as setInterval doesn’t guarantee an interval, your computer might be busy doing other things so you’d get a jerky animation rather than a smooth flow.

    Also to note that an interval of 5 milliseconds is very frequent given the refresh rate of the screen is likely to be 30/second so the user isn’t in fact seeing a pixel by pixel movement.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search