Fundamentals of Multimedia

Multimedia Demonstrations - HTML5 Animation Demo

HTML Canvas

<canvas> is a HTML element that we can draw graphics on it. It is like a container for our graphics. We can use JavaScript to draw graphics on <canvas>.

Demo

This demo is going to illustrate how to make lots of bouncing rainbow candies!
We need to have a canvas tag on our HTML file, which defines the area where we want to draw our graphics.

<canvas 
    id="my-canvas"
    width="400"
    height="400"
    style = "width: 400; height: 400;"
>
<canvas>

                
Then, we need to use JavaScript to select our canvas tag, and get the 2d context.

let canvasExample = document.getElementById("my-canvas");
ctx = canvasExample.getContext("2d");
                
Then, we want to create a class to represent the candies.
Below is the skeleton of our Candy class. We will add more things to the class as we continue.

function Candy(x, y, radius, color) {
    // x y represent the coordinate of the candy's position
    this.x = x
    this.y = y

    // radius represents the radius of our candy.
    this.radius = radius

    // this is the color of our candy
    this.color = color

    // Two reversed directions
    directions = [-1, 1];

    // The incremental movements for x-axis and y-axis
    this.xDirection = directions[Math.floor(Math.random() * directions.length)] * ((Math.random() * 5) + 1);
    this.yDirection =  directions[Math.floor(Math.random() * directions.length)] * ((Math.random() * 5) + 1);

    // This function will draw the candy on the canvas
    this.draw = (ctx) => {
        // ...
    }

    // This function updates the candy properties and re-draw the candy
    this.animate = (ctx) => {
        // ...
    }
}
                
Let's fill out the this.draw function.
The job of this.draw is to draw the Candy represented by this Candy class on canvas.
We need to pass ctx (the 2D context we get from canvas) to this this.draw function, and use ctx to draw a circle.

this.draw = (ctx) => {
    // Indicate that we are going to draw something
    ctx.beginPath();

    // Set the fill color
    ctx.fillStyle = this.color;

    // Draw an arc from coordinate x, y with given radius
    // Start the angle from 0 to 2*pi, which forms a circle
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);

    // Call this function to fill the color
    ctx.fill();
}
                
Now, let's try to instantiate this Candy class, call the draw function and see what happens.

let candy = new Candy(100, 100, 10, "red");
candy.draw(ctx);

                
As can bee seen from the above canvas, we have a red candy now. However, this candy is not moving.
To make the candy moving, we need to update the drawing for each given itnerval.
Let's fill out this.animate function.

this.animate = (ctx) => {
    // For each animatiton frame, we want to update the candy's position
    // by the pre-defined movements of x-axis and y-axis
    this.x += this.xDirection;
    this.y += this.yDirection;

    // Check if the candy hits the canvas boundaries.
    // If the candy hits the boundaries, it should bounce back,
    // so we reverse its direction by multiply it by -1
    if (this.x + this.radius > ctx.canvas.width || this.x - this.radius < 0) {
        // Reverse direction
        this.xDirection *= -1;
    }

    if (this.y + this.radius > ctx.canvas.height || this.y - this.radius < 0) {
        // Reverse direction
        this.yDirection *= -1;
    }

    // After updating the candy's position and direction,
    // re-draw the candy
    this.draw(ctx);
}

                
After we have filled out this.animate function, we need to use browser's window.requestAnimationFrame() API. This API is to tell browser that we want to perform an animation. Therefore, the browser will call the our specified function to update the object before re-painting. More details can be found here: MDN web docs: requestAnimationFrame

So, instead of calling this.draw(), we want to make a wrapper function to wrap everything and pass this function to window.requestAnimationFrame().

let candy = new Candy(100, 100, 10, "red");

// Wrapper function
let startAnimation = () => {
    // Before each re-painting, we need to clear previous painting from canvas
    ctx.clearRect(0, 0, canvasExample.width, canvasExample.height);

    // Call animate() to update Candy's movements and direction
    candy.animate(ctx);

    // Pass the wrapper function to browser's animation API
    requestAnimationFrame(startAnimation);
}

startAnimation();

                
Therefore, we can see this red candy is moving and bouncing in our canvas.
We can create more candies and apply the same things to get many colorful candies in the canvas.