Brian Montana

Posted on

# Canvas 101: Multiple Shapes and Resets

This tutorial will build off the previous post I made; Canvas 101: Rotating Shape, focusing on manipulating an array populated with objects created from a class.

The last tutorial we used the `Square` class to build an object that was updated over time with the `requestAnimationFrame`method. Now we'll create multiple `Square` instances, animate them across the canvas, and reset their position when they are completely off the screen.

To begin let's fork this pen to start:

First we will update the `Square` class with `xVelocity` in the deconstructed object of the constructor. We'll use this to move our square across the canvas, and rotate it as it moves. Setting a default value `0.1`, or another similar smaller value, in the constructor we'll set the `xVelocity` to a random value using its default value as the minimum and 1 as the maximum random value for `xVelocity`.

`this.xVelocity = Math.random() * (1 - xVelocity) + xVelocity;`

Now let's check out the `movement` function, right now we're incrementing the value by `0.1`, but with the randomly generated `xVelocity` we can increment it by the `xVelocity` value over time. Every time you refresh you'll see a different speed. The square will continue to move off the canvas but we can include a check for the current position of the square and reset it to the left side of the canvas using this check `shape.xPosition > canvasWidth + shape.width`. While doing this we'll want to set the new position to `-shape.width`, placing it just outside the canvas, so it moves into the canvas instead of appearing on the edge. Here's the final update for the `movement` function.

``````function movement(shape) {
if(shape.xPosition > canvasWidth + shape.width) {
shape.xPosition = -shape.width;
}
shape.rotate += shape.xVelocity / 15;
shape.xPosition += shape.xVelocity;
}
``````

Awesome! We're seeing the `Square` instance being animated and rendered across the canvas! Now we can setup an array and create multiple instances of `Square`. Create an array at the top `const squares = [];` and a value for the total count `let squareCount = 50;` Now we have an array to push generated instances of `Square`, while randomizing it's `xPosition`, and `yPosition`. The randomizing will use the same minimum and maximum threshold constraints in `xVelocity`, we can think of it like this `Math.random() * (max - min) + min`. To finalize it we'll use a `for` loop to populate our `squares` array with the limit of `squareCount`.

``````for (let i = 0; i < squareCount; i++) {
squares.push(
new Square({
width: 40,
height: 40,
xPosition:
Math.random() * (canvasWidth * 0.9 - canvasWidth * 0.1) +
canvasWidth * 0.1,
yPosition:
Math.random() * (canvasHeight * 0.9 - canvasHeight * 0.1) +
canvasHeight * 0.1
})
);
}
``````

Since the `squares` array is populated we'll need to update the `render` function to determine the updated values for each `Square` instance in the `squares` array. Let's use the `forEach` method provided by the `Array` object to update each element's values with the `movement` function, then drawing the results on the canvas. Each `Square` instance will draw on top of the last one, so the last element in the array will be drawn on top of all the previous elements.

``````function render() {
context.fillStyle = "lightsalmon";
context.fillRect(0, 0, canvasWidth, canvasHeight);
squares.forEach(square => {
movement(square);
context.save();
context.fillStyle = "salmon";
context.translate(square.xPosition, square.yPosition);
context.rotate(square.rotate);
context.fillRect(
-square.width / 2,
-square.height / 2,
square.width,
square.height
);
context.restore();
});
window.requestAnimationFrame(render);
}
``````

That should be it! Now all the squares will animate across the canvas and reset their position when they go off screen. See the results in the pen below :D