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>