View on GitHub

JS1 Help

How-To's from Mr. Hinkle's Intro to JavaScript Class

Canvas Animation Basics

Creating a Simple Animation

The basic steps of an animation involve drawing something repeatedly, making a small change to your drawing each time you draw it.

Prerequisites

Before you can animate, you need to create a canvas and have a reference to it in JavaScript. You also need to know how to make a basic drawing, whether that be a simple shape or drawing an image. Finally, you’ll need to know how to create variables to store information that you change.

The Simplest Animation: a dropping square

JavaScript: Assuming you have canvas and ctx defined

// Define a variable to hold our changing value
let y = 0;

// Define a function we call once per animation
function animateSquare () {
  // Clear the current drawing
  ctx.clearRect(0,0,canvas.width,canvas.height);  
  // Draw the rectangle at the new "y" value
  ctx.fillRect(10,y,50,50);
  // Add one to the y value
  y += 1;
  // Ask the browser to call us again at the animation frame
  requestAnimationFrame(animateSquare);
}

animateSquare();

Here it is live:

See the Pen Squares by Tom Hinkle (IACS) (@thinkle-iacs) on CodePen.

Getting Fancier: Using an Object to store information

Above, I included a simple variable, y, and only animated on part of the drawing. Often, we want to think of the thing we are animating as an object, which contains a number of changing properties, not just one.

We can use the object literal syntax to group any properties we want together into one object, like this:

let square = {
  x : 10,
  y: 10,
}

We can then use dot notation to update or read those values, like this:

function animateSquare () {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  ctx.fillRect(square.x, square.y, 100, 100);  
  square.x += 1;
  square.y += 1;

}

Once we’ve created an object, we can update all manner of properties on the object, as in this example:

let square = {
  x : 10,
  y : 10,
  vx : 10,
  vy : 10,
  s : 20,
  growing : true;
  color : 'red',
}

We can then use those properties to draw and move the square, like this…

ctx.fillStyle = square.color;
ctx.fillRect(square.x,square.y,square.s,square.s);
square.x += square.vx;
square.y += square.vy;

Finally, we can use if statements to check for things like when the square hits the edge of the screen, with lines like this:

if (square.x > canvas.width) {
  square.x = canvas.width; // stop square at canvas edge
  square.vx *= -1; // reverse velocity in the x direction
}

When we put it all together, we get something like this:

let square = {
  x: 10,
  y: 10,
  vx: 14,
  vy: 10,
  s: 20,
  growing: true,
  color: "red"
};

function animateSquare() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = square.color;
  ctx.fillRect(square.x, square.y, square.s, square.s);
  square.x += square.vx;
  square.y += square.vy;

  if (square.vx > 0) {
    square.color = "green";
  } else {
    square.color = "red";
  }
  if (square.x > canvas.width) {
    square.x = canvas.width;
    square.vx *= -1;
  }
  if (square.y > canvas.height) {
    square.y = canvas.height;
    square.vy *= -1;
  }
  if (square.y < 0) {
    square.y = 0;
    square.vy *= -1;
  }
  if (square.x < 0) {
    square.x = 0;
    square.vx *= -1;
  }
  if (square.growing) {
    square.s += 1;
  } else {
    square.s -= 1;
  }
  if (square.s < 5) {
    square.growing = true;
  }
  if (square.s > 50) {
    square.growing = false;
  }
  requestAnimationFrame(animateSquare);
}
animateSquare();

See the Pen Squares by Tom Hinkle (IACS) (@thinkle-iacs) on CodePen.

Tidying it Up with Function Calls

In practice, it can be better to break something like the above into multiple function calls to simplify our logic.


function animateSquare () {
  updateSquare(square);
  ctx.clearRect(0,0,canvas.width,canvas.height);
  drawSquare(square);
  requestAnimationFrame(animateSquare);
}

function drawSquare (square) {
  ctx.fillStyle = square.color;
  ctx.fillRect(square.x,square.y,square.s,square.s);
}

function updateSquare (square) {
  updateColor(square);
  updateVelocity(square);
  updatePosition(square);
  updateSize(square);
}

function updatePosition (square) {
  square.x += square.vx;
  square.y += square.vy;
  // Don't let square move outside of view...
  if (square.x < 0) {square.x = 0}
  if (square.y < 0) {square.y = 0}
  if (square.x > canvas.width) {square.x = canvas.width}
  if (square.y > canvas.height) {square.y = canvas.height}
}

function updateVelocity (square) {
  if (square.x >= canvas.width || square.x <= 0) {    
    square.vx *= -1;
  }
  if (square.y >= canvas.height || square.y <= 0) { 
    square.vy *= -1;
  }
}

function updateColor (square) {
  if (square.vx > 0) {
    square.color = 'red';
  } else {
    square.color = 'blue';
  }
}

function updateSize (square) {
  if (square.growing) {
    square.s += 1;
  } else {
    square.s -= 1;
  }
  if (square.s > 100) {
    square.growing = false;
  }
  if (square.s < 1) {
    square.growing = true;
  }
}

See the Pen Squares by Tom Hinkle (IACS) (@thinkle-iacs) on CodePen.

Creating a List of Objects to animate

In JavaScript, we can define a list with square brackets, like this:

let emptyList = [];

We can add items to a list by putting the items in the list separated with commas, like this:

let colors = ['red','blue','green','yellow'];

It is then easy to loop over items in a list by using the forEach method of a list to call a function for each item on a list.

Knowing all of this: it becomes very simple to refactor our earlier code to animate an entire list:

First, we replace our initial square with a list squares

let squares = [{
  x: 10,
  y: 10,
  vx: 14,
  vy: 10,
  s: 20,
  growing: true,
  color: "red"
},{
  x : 20,
  y:44,
  vx:-20,
  vy:-100,
  s:55,
  growing:false,
  color:'green'
}]

Second, we replace our calls to update an individual squares with forEach calls to update all squares, like this…

function animateSquares () {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  squares.forEach(updateSquare);
  squares.forEach(drawSquare);
  requestAnimationFrame(animateSquares);
}

See the Pen Squares by Tom Hinkle (IACS) (@thinkle-iacs) on CodePen.

Here’s a video walkthrough of me moving from a single animation to a list of animations: