I'm trying to move an element (with its own starting coordinates) to a custom position on the canvas.
How can I make it move to the new position directly (following a straight line)?
<html>
<head></head>
<body>
<canvas id="canvas" width="600px" height="600px"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var mouseX, mouseY;
document.addEventListener("click", function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
console.log(mouseX, mouseY)
})
function background() {
ctx.fillStyle = "#505050";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
var ball = {
x: 100,
y: 100,
draw: function () {
ctx.fillStyle = "#F00000";
ctx.beginPath();
ctx.arc(this.x, this.y, 30, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
}
}
setInterval(function () {
background();
ball.draw()
//example
if (mouseX > ball.x)
ball.x++;
if (mouseY > ball.y)
ball.y++;
}, 1000 / 60)
</script>
</body>
</html>
The thing under //example can work only for pure left/right/up/down/diagonal movement, but doesn't work as intended for custom locations other than those.
I want it to always travel directly to a custom location, following a straight line.
You should work with dx and dy to figure out how far to move each direction on each render. I also recommend to use window.requestAnimationFrame to call draw on each frame. You can also set stepWidthFactor relative to the distance.
<canvas id="canvas" width="600px" height="600px"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var stepWidthFactor = 200;
var mouseX, mouseY;
function background() {
ctx.fillStyle = "#505050";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
var ball = {
x: 100,
y: 100,
dx: 0,
dy: 0,
draw: function () {
ctx.fillStyle = "#F00000";
ctx.beginPath();
ctx.arc(this.x, this.y, 30, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
}
}
function draw() {
background();
ball.draw();
var shouldMove = Math.abs(ball.x - mouseX) > 1 || Math.abs(ball.y - mouseY) > 1;
if(shouldMove) {
ball.x += ball.dx;
ball.y += ball.dy;
} else {
ball.dx = 0;
ball.dy = 0;
}
window.requestAnimationFrame(draw)
}
document.addEventListener("click", function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
ball.dx = (ball.x - mouseX) / stepWidthFactor * -1;
ball.dy = (ball.y - mouseY) / stepWidthFactor * -1;
})
draw();
</script>
Related
Please look at the code for Canvas arrowhead why the arrowhead disappears every time you draw a new line. And how can I fix it? sorry for my english thank you
I want this section to be used to draw matching lines. But I have a problem with arrowheads. I hope someone can help me with a problem I'm not good at and can't find a solution.
https://jsfiddle.net/liptonkingza/4vn3uyb9/1/
Code
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var storedLines = [];
var startX = 0;
var startY = 0;
var isDown;
ctx.strokeStyle = "orange";
ctx.lineWidth = 3;
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function(e) {
handleMouseUp(e);
});
$("#clear").click(function() {
storedLines.length = 0;
redrawStoredLines();
});
function handleMouseDown(e) {
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
isDown = true;
startX = mouseX;
startY = mouseY;
}
function arrow (p1, p2, size) {
var angle = Math.atan2((p2.y - p1.y) , (p2.x - p1.x));
var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
ctx.save();
ctx.translate(p1.x, p1.y);
ctx.rotate(angle);
// line
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(hyp - size, 0);
ctx.stroke();
// triangle
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.lineTo(hyp - size, size);
ctx.lineTo(hyp, 0);
ctx.lineTo(hyp - size, -size);
ctx.fill();
ctx.restore();
}
function handleMouseMove(e) {
if (!isDown) {
return;
}
redrawStoredLines();
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
// draw the current line
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(mouseX, mouseY);
arrow({x: startX, y: startY}, {x: mouseX, y: mouseY}, 10);
ctx.stroke();
}
function handleMouseUp(e) {
isDown = false;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
storedLines.push({
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY
});
redrawStoredLines();
arrow({x: startX, y: startY}, {x: mouseX, y: mouseY}, 10);
}
function redrawStoredLines() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (storedLines.length == 0) {
return;
}
// redraw each stored line
for (var i = 0; i < storedLines.length; i++) {
ctx.beginPath();
ctx.moveTo(storedLines[i].x1, storedLines[i].y1);
ctx.lineTo(storedLines[i].x2, storedLines[i].y2);
ctx.stroke();
}
}
body {
background-color: ivory;
padding: 10px;
}
canvas {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Drag to draw lines</p>
<canvas id="canvas" width=300 height=300></canvas>
<br/>
<button id="clear">Clear Canvas</button>
Your redrawStoredLines function is only drawing lines and not including the arrow.
Replace this:
function redrawStoredLines() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (storedLines.length == 0) {
return;
}
// redraw each stored line
for (var i = 0; i < storedLines.length; i++) {
ctx.beginPath();
ctx.moveTo(storedLines[i].x1, storedLines[i].y1);
ctx.lineTo(storedLines[i].x2, storedLines[i].y2);
ctx.stroke();
}
}
With:
function redrawStoredLines() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (storedLines.length == 0) {
return;
}
// redraw each stored line
for (var i = 0; i < storedLines.length; i++) {
arrow({x: storedLines[i].x1, y: storedLines[i].y1}, {x: storedLines[i].x2, y: storedLines[i].y2}, 10);
}
}
See it in action...
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var storedLines = [];
var startX = 0;
var startY = 0;
var isDown;
ctx.strokeStyle = "orange";
ctx.lineWidth = 3;
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function(e) {
handleMouseUp(e);
});
$("#clear").click(function() {
storedLines.length = 0;
redrawStoredLines();
});
function handleMouseDown(e) {
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
isDown = true;
startX = mouseX;
startY = mouseY;
}
function arrow (p1, p2, size) {
var angle = Math.atan2((p2.y - p1.y) , (p2.x - p1.x));
var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
ctx.save();
ctx.translate(p1.x, p1.y);
ctx.rotate(angle);
// line
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(hyp - size, 0);
ctx.stroke();
// triangle
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.lineTo(hyp - size, size);
ctx.lineTo(hyp, 0);
ctx.lineTo(hyp - size, -size);
ctx.fill();
ctx.restore();
}
function handleMouseMove(e) {
if (!isDown) {
return;
}
redrawStoredLines();
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
// draw the current line
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(mouseX, mouseY);
arrow({x: startX, y: startY}, {x: mouseX, y: mouseY}, 10);
ctx.stroke();
}
function handleMouseUp(e) {
isDown = false;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
storedLines.push({
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY
});
redrawStoredLines();
arrow({x: startX, y: startY}, {x: mouseX, y: mouseY}, 10);
}
function redrawStoredLines() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (storedLines.length == 0) {
return;
}
// redraw each stored line
for (var i = 0; i < storedLines.length; i++) {
arrow({x: storedLines[i].x1, y: storedLines[i].y1}, {x: storedLines[i].x2, y: storedLines[i].y2}, 10);
}
}
body {
background-color: ivory;
padding: 10px;
}
canvas {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Drag to draw lines</p>
<canvas id="canvas" width=300 height=300></canvas>
<br/>
<button id="clear">Clear Canvas</button>
I have a blue circle which is rotating around the red circle and moves on canvas continuously in one direction as long as the button is pressed.
Now I want to draw with the red circle while it is moving when the button is pressed (trace of its path).
Problems:
when i try to draw on the canvas by not using clearRect(0,0, canvas.width, canvas.height); the blue circle also starts to draw on the canvas while moving which I don't need.
Is it possible to draw with one circle and to not draw with another circle on same canvas?
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100;
let positionY = 100;
let X = 50;
let Y = 50;
let angle = 0;
let mouseButtonDown = false;
document.addEventListener('mousedown', () => mouseButtonDown = true);
document.addEventListener('mouseup', () => mouseButtonDown = false);
function circle(){
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(X, Y, 20, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function direction(){
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI*2);
ctx.closePath();
positionX = 35 * Math.sin(angle);
positionY = 35 * Math.cos(angle);
ctx.fill();
}
function animate(){
if (mouseButtonDown) {
X += positionX / 10;
Y += positionY / 10;
} else {
angle += 0.1;
}
ctx.clearRect(0,0, canvas.width, canvas.height);
circle();
direction();
requestAnimationFrame(animate);
}
animate();
#canvas1{
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas basics</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>
We could introduce a new variable:
let history = [{X,Y}]
there we can keep the positions of the red circle as it moves, and we keep everything else in your code the same, we still use clearRect to clear and then redraw all elements.
On my sample code I'm pushing items to the history on mouseup that means that history won't show until the move is done, but you can play with that see if some other event has a better experience... same with what is drawn from history, I'm drawing a dashed line but it can be anything else.
Only thing I changed was the angle angle += 0.05; it was a bit fast for me.
My sample code below will draw something like this:
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let positionX = 100
let positionY = 100
let X = canvas.width / 2;
let Y = canvas.height / 2;
let angle = 0;
let mouseButtonDown = false;
let history = [{ X, Y }]
document.addEventListener('mousedown', mousedown);
document.addEventListener('mouseup', mouseup);
function mousedown() {
mouseButtonDown = true
}
function mouseup() {
mouseButtonDown = false
history.push({ X, Y })
}
function drawHistory() {
// draw the lines for history
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.setLineDash([5, 5]);
ctx.moveTo(history[0].X, history[0].Y)
for (let i = 1; i < history.length; i++) {
ctx.lineTo(history[i].X, history[i].Y)
}
ctx.stroke();
ctx.closePath();
// draw line for current movement
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.setLineDash([10, 2]);
ctx.moveTo(history[history.length-1].X, history[history.length-1].Y)
ctx.lineTo(X, Y)
ctx.stroke();
ctx.closePath();
}
function circle() {
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(X, Y, 20, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
function direction() {
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(positionX + X, positionY + Y, 10, 0, Math.PI * 2);
ctx.closePath();
positionX = 35 * Math.sin(angle);
positionY = 35 * Math.cos(angle);
ctx.fill();
}
function animate() {
if (mouseButtonDown) {
X += positionX / 10;
Y += positionY / 10;
} else {
angle += 0.05;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle();
direction();
drawHistory();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas1"></canvas>
I need to make a game where a ball drops and cannot hit the floor, and you have to make it bounce again before it hits the ground, but I don't know how to make the ball jump when the mouse clicks!
How do I make a reaction to thew mouse clicking on the screen?
var canvas, ctx, container;
canvas = document.createElement('canvas');
ctx = canvas.getContext("2d");
var ball;
// Velocity y - randomly set
var vy;
var gravity = 0.5;
var bounce = 0.7;
var xFriction = 0.1;
function init() {
setupCanvas();
vy = (Math.random() * -15) + -5;
ball = {
x: canvas.width / 2,
y: 100,
radius: 20,
status: 0,
color: "red"
};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, false);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.closePath()
ballMovement();
}
setInterval(draw, 1000 / 35);
function ballMovement() {
ball.y += vy;
vy += gravity;
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
vx *= -1;
}
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
vy *= -bounce;
vy = 0;
if (Math.abs(vx) < 1.1)
vx = 0;
xF();
}
}
function setupCanvas() { //setup canvas
container = document.createElement('div');
container.className = "container";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(container);
container.appendChild(canvas);
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 2;
}
You just have to make an event listener as follows
window.addEventListener('click', function(event) {
//code here
})
//but if you want it so it's just on the canvas
canvas.addEventListener('click', function(event) {
//code here
})
So I am following this code to implement rotate function in my paint program:
http://jsfiddle.net/QqwKR/412/
However, the image img doesn't load up and instead a yellow filled rectangle shows up.
Also when I add the rotate function, the code stops working:
function rotate() {
flag = 4;
var img = new Image();
img.onload = function () {
w = img.width / 2;
h = img.height / 2;
draw();
}
img.src = "https://image.flaticon.com/teams/new/1-freepik.jpg";
}
In html I add the following:
<button onclick="rotate()" style="height:100px;width:100px;">rotate</button>
Any ideas why this is happening?
A big yellow rectangle shows up because you draw a big yellow rectangle over the image. Copied from the code:
function drawRect() {
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(r);
ctx.drawImage(img, 0, 0, img.width, img.height, -w / 2, -h / 2, w, h);
ctx.fillStyle="yellow";
ctx.fillRect(-w/2,-h/2,w,h); // <-- Here.
ctx.restore();
}
If you remove those two lines, the handle works just fine.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var startX;
var startY;
var isDown = false;
var cx = canvas.width / 2;
var cy = canvas.height / 2;
var w;
var h;
var r = 0;
var img = new Image();
img.onload = function () {
w = img.width / 2;
h = img.height / 2;
draw();
}
img.src = "https://image.flaticon.com/teams/new/1-freepik.jpg";
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawRotationHandle(true);
drawRect();
}
function drawRect() {
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(r);
ctx.drawImage(img, 0, 0, img.width, img.height, -w / 2, -h / 2, w, h);
ctx.restore();
}
function drawRotationHandle(withFill) {
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(r);
ctx.beginPath();
ctx.moveTo(0, -1);
ctx.lineTo(w / 2 + 20, -1);
ctx.lineTo(w / 2 + 20, -7);
ctx.lineTo(w / 2 + 30, -7);
ctx.lineTo(w / 2 + 30, 7);
ctx.lineTo(w / 2 + 20, 7);
ctx.lineTo(w / 2 + 20, 1);
ctx.lineTo(0, 1);
ctx.closePath();
if (withFill) {
ctx.fillStyle = "blue";
ctx.fill();
}
ctx.restore();
}
function handleMouseDown(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
drawRotationHandle(false);
isDown = ctx.isPointInPath(mouseX, mouseY);
// console.log(isDown);
}
function handleMouseUp(e) {
isDown = false;
}
function handleMouseOut(e) {
isDown = false;
}
function handleMouseMove(e) {
if (!isDown) {
return;
}
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
var dx = mouseX - cx;
var dy = mouseY - cy;
var angle = Math.atan2(dy, dx);
r = angle;
draw();
}
$("#canvas").mousedown(function (e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function (e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function (e) {
handleMouseUp(e);
});
$("#canvas").mouseout(function (e) {
handleMouseOut(e);
});
body {
background-color: ivory;
}
#canvas {
border:1px solid red;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<p>Rotate by dragging blue rotation handle</p>
<canvas id="canvas" width=300 height=300></canvas>
Regarding the button and the rotate function, I have no idea what you want to achieve with that.
I have a ball that drops from cursor location, and redrops when the cursor is moved to another location. I am trying get a new ball to drop every time I click the mouse. I tried:
canvas.addEventListener('click', function(event) {
ball.draw();
});
But it doesn't seem to do anything. Is there some way to draw a NEW ball on click instead of just redrawing the same ball over and over again?
Here's the rest of the code:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
var W = window.innerWidth,
H = window.innerHeight;
var running = false;
canvas.height = H; canvas.width = W;
var ball = {},
gravity = .5,
bounceFactor = .7;
ball = {
x: W,
y: H,
radius: 15,
color: "BLUE",
vx: 0,
vy: 1,
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
};
function clearCanvas() {
ctx.clearRect(0, 0, W, H);
}
function update() {
clearCanvas();
ball.draw();
ball.y += ball.vy;
ball.vy += gravity;
if(ball.y + ball.radius > H) {
ball.y = H - ball.radius;
ball.vy *= -bounceFactor;
}
}
canvas.addEventListener("mousemove", function(e){
ball.x = e.clientX;
ball.y = e.clientY;
ball.draw();
});
setInterval(update, 1000/60);
ball.draw();
Just rewrite the ball object so it becomes instantiate-able:
function Ball(W, H) {
this.x = W;
this.y = H;
this.radius = 15;
this.color = "blue";
this.vx = 0;
this.vy = 1;
}
Move the methods to prototypes (this will make them shareable across instances). In addition, add an update method so you can localize updates:
Ball.prototype = {
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
},
update: function() {
this.y += this.vy;
this.vy += gravity;
if(this.y + this.radius > H) {
this.y = H - this.radius;
this.vy *= -bounceFactor;
}
}
};
In the click event (consider renaming the array to plural form - it's easier to distinguish that way. In your code you're overriding the "array" (which is defined as an object) with a single ball object later):
var balls = []; // define an array to hold the balls
For the click event to use the x and y position of the mouse as start point for the ball, we first need to adjust it as it is relative to client window and not the canvas. To do this we get the absolute position of canvas and subtract it from the client coordinates:
canvas.addEventListener('click', function(event) {
var rect = this.getBoundingClientRect(), // adjust mouse position
x = event.clientX - rect.left,
y = event.clientY - rect.top;
balls.push(new Ball(x, y)); // add a new instance
});
Now in the main animation loop just iterate over the array. Every time there is a new ball it will be considered and updated - we just let the loop run until some condition is met (not shown):
function update() {
clearCanvas();
for(var i = 0, ball; ball = balls[i]; i++) {
ball.draw(); // this will draw current ball
ball.update(); // this will update its position
}
requestAnimationFrame();
}
Live example
If you put these together you will get:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
W = canvas.width, // simplified for demo
H = canvas.height,
gravity = .5,
bounceFactor = .7;
function Ball(x, y) {
this.x = x;
this.y = y;
this.radius = 15;
this.color = "blue";
this.vx = 0;
this.vy = 1
}
Ball.prototype = {
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
},
update: function() {
this.y += this.vy;
this.vy += gravity; // todo: limit bounce at some point or this value will be added
if (this.y + this.radius > H) {
this.y = H - this.radius;
this.vy *= -bounceFactor;
}
}
};
function clearCanvas() {
ctx.clearRect(0, 0, W, H);
}
var balls = []; // define an array to hold the balls
canvas.addEventListener('click', function(event) {
var rect = this.getBoundingClientRect(), // adjust mouse position
x = event.clientX - rect.left,
y = event.clientY - rect.top;
balls.push(new Ball(x, y)); // add a new instance
});
(function update() {
clearCanvas();
for (var i = 0, ball; ball = balls[i]; i++) {
ball.draw(); // this will draw current ball
ball.update(); // this will update its position
}
requestAnimationFrame(update);
})();
canvas {background:#aaa}
<canvas id="canvas" width=600 height=400></canvas>