DEV Community

Cover image for JS Animation
Liam Escribano
Liam Escribano

Posted on

JS Animation

Hello and good morning! Today I will be showing you how to turn a sprite sheet into an animation sequence using JavaScript. Here is the sprite sheet we will be working with and the final result.

Dog Sprite Sheet
Dog Walking

Prerequisites

  • An understanding of the HTML canvas and context
  • Basic knowledge of JavaScript classes
  • A bit of async and await

Things to note about this sprite sheet

  • Has a total of 8 frames
  • Each frame is exactly 113x79 pixels

Our First Class

class Sprite {
  constructor(src, width, height, frames) {
    this.image = new Image;
    this.image.src = src;
    this.width = width;
    this.height = height;
    this.frames = frames;
  }
}
Enter fullscreen mode Exit fullscreen mode

This class is in charge of maintaining the properties of a sprite sheet. The width and height properties belong to the expected width/height for all of the frames in the sheet (113x79).

The Animation Handler

class AnimationHandler {
  constructor(sprites) {
    this.sprites = sprites;
    this.currentSprite = sprites[0];
    this.loop = true;
    this.currentSprite.image.onload = this.render();
  }
...
Enter fullscreen mode Exit fullscreen mode

The AnimationHandler class takes in an array of Sprite Objects and calls the render function in a looping state after the sprite loads.

The Brains

...
async render() {
    for (let i = 0; i < this.currentSprite.frames; i++) {
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.drawImage(this.currentSprite.image, (this.currentSprite.width * i), 0, this.currentSprite.width, 
      this.currentSprite.height, 50, 50, this.currentSprite.width, this.currentSprite.height);

      await sleep(80)
    }
    if (this.loop) {this.render();}
  }
Enter fullscreen mode Exit fullscreen mode

We first define an asynchronous function named render using the async keyword. This allows us to run multiple animations at once without creating blockage.

We then create a basic for loop to loop over the number of frames. For every frame we do these things in order.

  1. Clear everything on the canvas
  2. Draw the sprite image and crop it to show the current frame
  3. Pause the loop for 80 milliseconds before continuing
  4. Use recursion to keep the animation running

Check this link out to learn about how context.drawImage works MDN

You may be asking yourself, "Where the hell is the sleep function defined?!" I decided to keep it out of this tutorial to avoid confusion. The sleep function just returns a Promise after setTimeout.

Putting It All Together

const dogIdle = new Sprite(dog_idle, 109, 79, 4);
const dogMoving = new Sprite(dog_moving, 113, 79, 8);
new AnimationHandler([dogMoving, dogIdle])
Enter fullscreen mode Exit fullscreen mode

We create two Sprite instances and pass in the required parameters. Then we create an AnimationHandler instance for the sprites. This should automatically play the first sprite sheet you pass i although the class can be easily modified to jump between animations and even pause them.

Here is the idle we defined above and an attacking animation.

sheet
dog idle
attacking

Thank you for reading ! I left a few things out for the sake of keeping this simple. Like defining the canvas and context and the sleep function.

Top comments (0)