Skip to content
Advertisement

How can I perform a reset on the loop I have when pressing a button?

I’m creating a code where 3 balls will bounce when a button is clicked. I have a code I found in the internet and added the start button but clicking it multiple times speed up the balls. Also, I tried adding a reset button that will clear out the canvas but can’t make it work. Sharing both the HTML and JS code.

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width = 1000;
const height = canvas.height = 500;
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);

function random(min, max) {
  const num = Math.floor(Math.random() * (max - min + 1)) + min;
  return num;
}

function Ball(x, y, velX, velY, color, size) {
  this.x = x;
  this.y = y;
  this.velX = velX;
  this.velY = velY;
  this.color = color;
  this.size = size;
}
Ball.prototype.draw = function() {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
  ctx.fill();
}
Ball.prototype.update = function() {
  if ((this.x + this.size) >= width) {
    this.velX = -(this.velX);
  }
  if ((this.x - this.size) <= 0) {
    this.velX = -(this.velX);
  }
  if ((this.y + this.size) >= height) {
    this.velY = -(this.velY);
  }
  if ((this.y - this.size) <= 0) {
    this.velY = -(this.velY);
  }
  this.x += this.velX;
  this.y += this.velY;
}
let balls = [];

function loop() {
  while (balls.length < 3) {
    let size = 35;
    let ball = new Ball(
      random(0 + size, width - size), random(0 + size, height - size), 5, 5, 'yellow', size);
    balls.push(ball);
  }
  ctx.fillStyle = 'grey';
  ctx.fillRect(0, 0, width, height);
  for (let i = 0; i < balls.length; i++) {
    balls[i].draw();
    balls[i].update();
  }
  requestAnimationFrame(loop);
}

document.getElementById('Begin').addEventListener('click',loop);
<input type='button' id='Begin' value='start'>
<canvas id='myCanvas'></canvas>

Advertisement

Answer

You need to store the requestAnimationFrame in a var and use cancelAnimationFrame to stop

I added a div to hold the buttons and now delegate from that div so only one event handler is needed.

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width = 1000;
const height = canvas.height = 500;
ctx.fillStyle = 'grey';
ctx.fillRect(0, 0, width, height);
let rq; // this we can use to request and cancel


function random(min, max) {
  const num = Math.floor(Math.random() * (max - min + 1)) + min;
  return num;
}

function Ball(x, y, velX, velY, color, size) {
  this.x = x;
  this.y = y;
  this.velX = velX;
  this.velY = velY;
  this.color = color;
  this.size = size;
}
Ball.prototype.draw = function() {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
  ctx.fill();
}
Ball.prototype.update = function() {
  if ((this.x + this.size) >= width) {
    this.velX = -(this.velX);
  }
  if ((this.x - this.size) <= 0) {
    this.velX = -(this.velX);
  }
  if ((this.y + this.size) >= height) {
    this.velY = -(this.velY);
  }
  if ((this.y - this.size) <= 0) {
    this.velY = -(this.velY);
  }
  this.x += this.velX;
  this.y += this.velY;
}
let balls = [];

function loop() {
  while (balls.length < 3) {
    let size = 35;
    let ball = new Ball(
      random(0 + size, width - size), random(0 + size, height - size), 5, 5, 'yellow', size);
    balls.push(ball);
  }
  ctx.fillStyle = 'grey';
  ctx.fillRect(0, 0, width, height);
  for (let i = 0; i < balls.length; i++) {
    balls[i].draw();
    balls[i].update();
  }
  rq = requestAnimationFrame(loop);
}

document.getElementById('butDiv').addEventListener('click', function(e) {
  const tgt = e.target;
  if (tgt.id === "Begin") {
    if (tgt.value === "start") {
      loop()
      tgt.value = "stop";
      document.getElementById("resetCanvas").classList.add("hide");
    } else {
      cancelAnimationFrame(rq)
      this.value = "start";
      document.getElementById("resetCanvas").classList.remove("hide");
    }
  } else if (tgt.id === "resetCanvas") {
    cancelAnimationFrame(rq)
    ctx.fillStyle = 'grey';
    ctx.fillRect(0, 0, width, height);
    document.getElementById("Begin").value="start";
    tgt.classList.add("hide");
  }
})
.hide {
  display: none;
}
<div id="butDiv">
  <input type='button' id='Begin' value='start'> <input type='button' class="hide" id='resetCanvas' value='reset'>
</div>
<canvas id='myCanvas'></canvas>
Advertisement