Search code examples
javascripthtmljquerycss

How do I move multiple balls


How do I add multiple balls to move? Please help.

Here is the code for ball and how it bounces - review it.

I think its the obj name that's the problem. I can't manage to make new name on every time a new obj is created.

I also tried jQuery to add multiple ball elements, but that also does not work

// code for ball
const INITIAL_VELOCITY = 0.085
const VELOCITY_CHANGE_RATE = 0
class Ball {
  constructor(ballElem) {
    this.ballElem = ballElem
    this.reset()
  }
  get x() {
    return parseFloat(getComputedStyle(this.ballElem).getPropertyValue("--x"))
  }
  set x(value) {
    this.ballElem.style.setProperty("--x", value)
  }
  get y() {
    return parseFloat(getComputedStyle(this.ballElem).getPropertyValue("--y"))
  }
  set y(value) {
    this.ballElem.style.setProperty("--y", value)
  }
  rect() {
    return this.ballElem.getBoundingClientRect()
  }
  reset() {
    this.x = 50
    this.y = 50
    this.direction = {x : 0}
    while (Math.abs(this.direction.x) <= 0.1 || Math.abs(this.direction.x) >= 0.9) {
      const heading = randomNumberBetween(0, 2 * Math.PI)
      this.direction = { x: Math.cos(heading), y: Math.sin(heading) }
    }
    this.velocity = INITIAL_VELOCITY
  }
update(delta,index) {
console.log(delta,index)
    this.x += this.direction.x * this.velocity * delta
    this.y += this.direction.y * this.velocity * delta
    // this.velocity += VELOCITY_CHANGE_RATE * delta
    // this.velocity -= VELOCITY_CHANGE_RATE / delta
    const rect = this.rect()

    if (rect.bottom >= window.innerHeight || rect.top <= 0) {
      this.direction.y *= -1
    }
    if (rect.right >= window.innerWidth || rect.left <= 0) {
      this.direction.x *= -1
    }

    //background color
    const hue = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--hue"));
    document.documentElement.style.setProperty("--hue", hue + delta * 0.02)
  }
}
function randomNumberBetween(min, max) {
  return Math.random() * (max - min) + min
}
var ballarr = []

for(var i = 0; i <= 10; i++){
    document.querySelector('body').innerHTML +=  `<div class="ball" id="ball${i}"></div>`

    ballarr[i] = new Ball(document.querySelector(`#ball${i}`))
}

console.log(ballarr)
// const ball = new Ball(document.querySelector("#ball"))

let lastTime
function updateTime(time) {
  if (lastTime != null) {
    const delta = time -  lastTime
    
   ballarr.map((val, index) => {
   val.update(delta, index)
   
   })
  }
  lastTime = time
  window.requestAnimationFrame(updateTime)
}
*,
*::after,
*::before {
  box-sizing: border-box;
}

 :root {
  --hue: 200;
  --saturation: 50%;
  --foreground-color: hsl(var(--hue), var(--saturation), 75%);
  --background-color: hsl(var(--hue), var(--saturation), 20%);
}

body {
  margin: 0;
  overflow: hidden;
}

.ball {
  --x: 50;
  --y: 50;
  position: absolute;
  /*background-color: var(--foreground-color); */
  /*background-color: #13ecb6;*/
  background-color: black;
  /*border: 4px solid #13ecb6;*/
  left: calc(var(--x) * 1vw);
  top: calc(var(--y) * 1vh);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  width: 3vh;
  height: 3vh;
}
<div class="ball" id="ball"></div>


Solution

  • The issue is due to how you create the balls and add them to the DOM and your ballarr array:

    var ballarr = []
    for (var i = 0; i <= 10; i++) {
      const ballEl = document.createElement('div');
      ballEl.classList.add('ball');
      document.body.appendChild(ballEl);
      const ball = new Ball(ballEl);
      ballarr.push(ball);
    }
    

    You also need to use forEach() to loop through the array to update ball positions, not map():

    ballarr.forEach(ball => ball.update(delta));
    

    Here's a full working example:

    // code for ball
    const INITIAL_VELOCITY = 0.085
    const VELOCITY_CHANGE_RATE = 0
    
    class Ball {
      constructor(ballElem) {
        this.ballElem = ballElem
        this.reset()
      }
      get x() {
        return parseFloat(getComputedStyle(this.ballElem).getPropertyValue("--x"))
      }
      set x(value) {
        this.ballElem.style.setProperty("--x", value)
      }
      get y() {
        return parseFloat(getComputedStyle(this.ballElem).getPropertyValue("--y"))
      }
      set y(value) {
        this.ballElem.style.setProperty("--y", value)
      }
      rect() {
        return this.ballElem.getBoundingClientRect()
      }
      reset() {
        this.x = 50
        this.y = 50
        this.direction = {
          x: 0
        }
        while (Math.abs(this.direction.x) <= 0.1 || Math.abs(this.direction.x) >= 0.9) {
          const heading = randomNumberBetween(0, 2 * Math.PI)
          this.direction = {
            x: Math.cos(heading),
            y: Math.sin(heading)
          }
        }
        this.velocity = INITIAL_VELOCITY
      }
      update(delta) {
        this.x += this.direction.x * this.velocity * delta
        this.y += this.direction.y * this.velocity * delta
        const rect = this.rect()
    
        if (rect.bottom >= window.innerHeight || rect.top <= 0) {
          this.direction.y *= -1
        }
        if (rect.right >= window.innerWidth || rect.left <= 0) {
          this.direction.x *= -1
        }
    
        //background color
        const hue = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--hue"));
        document.documentElement.style.setProperty("--hue", hue + delta * 0.02)
      }
    }
    
    function randomNumberBetween(min, max) {
      return Math.random() * (max - min) + min
    }
    
    var ballarr = []
    for (var i = 0; i <= 10; i++) {
      const ballEl = document.createElement('div');
      ballEl.classList.add('ball');
      document.body.appendChild(ballEl);
      const ball = new Ball(ballEl);
      ballarr.push(ball);
    }
    
    let lastTime
    
    function updateTime(time) {
      if (lastTime != null) {
        const delta = time - lastTime
        ballarr.forEach(ball => ball.update(delta));
      }
      lastTime = time
      window.requestAnimationFrame(updateTime)
    }
    
    updateTime(lastTime);
    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }
    
     :root {
      --hue: 200;
      --saturation: 50%;
      --foreground-color: hsl(var(--hue), var(--saturation), 75%);
      --background-color: hsl(var(--hue), var(--saturation), 20%);
    }
    
    body {
      margin: 0;
      overflow: hidden;
    }
    
    .ball {
      --x: 50;
      --y: 50;
      position: absolute;
      /*background-color: var(--foreground-color); */
      /*background-color: #13ecb6;*/
      background-color: black;
      /*border: 4px solid #13ecb6;*/
      left: calc(var(--x) * 1vw);
      top: calc(var(--y) * 1vh);
      border-radius: 50%;
      transform: translate(-50%, -50%);
      width: 3vh;
      height: 3vh;
    }