Canvas 101: Multiple Shapes and Resets
Tags: javascript, creativecoding, tutorial, codepen
Published: 2019-08-20 17:55:02

This tutorial will build off the previous post I made; [Canvas 101: Rotating Shape](https://dev.to/brianmontanaweb/canvas-101-rotating-shape-28la), 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:
{% codepen https://codepen.io/brianmontanaweb/pen/jgWPmV %}

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

{% codepen https://codepen.io/brianmontanaweb/pen/Qevpdb %}