Welcome to the next lesson of our JavaScript online course. The previous
lesson, 2D canvas context in JavaScript, was about the 2D context of a canvas. In today's JavaScript
tutorial, we're going to look at timing and then continue with animations.

Timers

We can handle timers in JavaScript using two functions.

setInterval() and setTimeout()

The setInterval() and setTimeout() functions accept
two parameters. The function that will be called and the time interval (how
often or after what time it'll be called). We specify the intervals in
milliseconds (1 second = 1000 milliseconds). The difference between these two
methods is quite fundamental. While setInterval() will call the
method every X milliseconds, setTimeout() will call it only once
when X milliseconds elapses.

Example

The goal will be to create a typing text. At first, the letter
"H" will show. One second later, "e" will show up.
This will continue with letters "l", "l",
"o", "w", "o", "r",
"l", "d". Once all the letters are typed, the text is
cleared and it all starts again.

Now we won't have any element in the HTML code anymore, we'll create it via
JavaScript (the implementation is only up to us, but we'll leave the
<body> empty to practice the DOM manipulation ).

We'll store the text to be typed into a text variable and create
a <p> element. Since it can happen that even the
<body> wouldn't be loaded yet (if we imported the script in
the <head>), we'll insert the <p> element
into the <body> element not before the page is loaded.

Now we'll proceed to the function which will be changing the text in our
element:

function changeText() {
}

At first in this function, we'll verify that we haven't already written all
the letters. If we asked for the next letter when we're at the end and there're
no more letters left, we'd cause an error. If the text variable
already equals to the element's content, we'll change the element's value to an
empty string so that the text can be typed again. We'll also add the else branch
where we'll insert further code.

Next, we'll retrieve the letter (character) which we'll add to the element's
text. We already know that length contains a string's length. So
we'll get the next character to be typed by measuring the length of the string
that is already typed on the screen and adding 1 to it. There's a catch. While
the string length is counted from 1 (1 character = length 1), the character at a
certain position (index) is counted from zero (1st character = index 0), so we
have to subtract 1. Finally +1 (for the next character) and -1 (because 0 is the
first character) eliminates, so we take the character at the index of the length
of the text already typed on the screen:

let letterToType = text[element.textContent.length];

And we add the letter to the text of the element.

element.textContent += letterToType;

All we have to do is to set the interval now. Let's call the
setInterval() method in the onload event handler.
We'll pass changeText as the name of the function (without
parentheses) as the first parameter, and the number 1000 to make
the text change every 1 second as the second parameter.

setInterval(changeText, 1000);

The interval will start one second later. In the meantime, the application
will look like it doesn't respond for a second. That's why we'll call the
changeText() method manually above it:

changeText();
setInterval(changeText, 1000);

You can still improve the application since it'll appear stuck when typing
whitespaces.

Typing text

localhost

Advanced animations

It'd be nice to have more complex animations on our website. The simple ones
can be done in CSS, but the more complicated ones have to be done in JavaScript.
The core principle of animations is that we affect properties of the animated
object in some interval.

Let's take autumn web decorations as an example. We'll program a script that
animates falling leaves, they'll fall from top to bottom. We'll place the images
of the leaves in the root <body> element and each image will
have a data-autumn data-attribute. We'll select only these images,
because there might be (and will be) other images on the website and we won't
want to animate those.

Download the leaf image below and put it into a new project with the
following HTML contents:

Let's attach a CSS style to the project in which we'll set the absolute
position to the images (again, we'll affect only the images with the
data-autumn attribute). We'll also style the
<body> so it won't display scrollbars.

We want to set the default position to the leaves. This will be one-fifth of
the window width for each leaf from the left (to justify them, as can be seen
further). And minus their height from the top (so they'd fall from behind the
top window edge).

Window size

Sometimes (like now) we need to work with window size. There're several ways
and properties out there that are related to this size.

The actual screen size

We can retrieve the real screen size using the width and
height properties on the screen object.

Available size

This is the size that applications can use. In other words, essentially the
screen size above minus the size of the system panels (such as the taskbar). We
can find the properties on the screen object again, they're
availWidth and availHeight.

The website window size

Finally, we're getting to the most important size for us. It's the size of
the area our applications can use. We can find the properties on the
window object as innerWidth and
innerHeight.

Setting CSS properties

For the time being, we still lack one essential piece of information which is
how to set CSS properties of DOM elements.

All DOM elements have the style property which contains
properties named as CSS properties. They're not written using the dash notation,
but camelCase (the first word is all in lowercase letters, each new word has the
first letter upper-cased, there're no spaces). So for example:

document.body.style.backgroundColor = "red";

sets the color of the <body> element to red.

Let's go back to our falling leaves. We'll set the positions. Remember to not
forget to specify the units when setting CSS values:

Moving the leaves

Now let's implement a move() function which will move the leaves
down. The function will iterate through all the leaves using a loop and set the
new positions to them. The new position will be based on the actual one (which
we must parse to remove the CSS unit from the value), and then we'll add some
reasonable value to it so the animation will be neither too fast nor too slow.
You can try to edit the value (the value 2 in the code).

We still have to deal with the case when a leaf leaves the window. In this
case, we need to reset its position to minus the height of the image. Let's
place a condition between the previous two lines so we don't have to set the CSS
value twice.

Run the application. You'll see the leaves falling from top to bottom, and
they'll reset once they leave the screen.

Falling leaves

localhost

Congratulations, you've finished your first JavaScript animation. You can
improve it, of course, to make it even more interesting.

Canvas animations

We can create animations using <canvas> in a similar way.
In some interval, we'll clear the entire canvas, draw everything and so over and
over again. We can program a wheel of fortune as an example. We'll load it from
a static image to keep things simple. So, let's create a page with a
<canvas> in it and select it in JavaScript. We'll add an
image with id="wheel" to the page.

Download the image below and insert it along with the following HTML code to
a new project:

In the redraw() method, we simply clear the canvas and draw the
wheel again. First, we'll move and rotate the context appropriately and then
we'll draw the image. Finally, we'll add one degree to the angle which
corresponds with Math.PI / 180 radians since Math.PI
is one half of the circle and one half of the circle has 180 degrees.

In the page's load event, we'll set the interval as usual. We'll
also draw the wheel right at the start so we won't have to wait for the first
interval to come.

setInterval(redraw, 20);
redraw();

The result:

Wheel of fortune

localhost

Congratulations, you should be now able to handle animations. You can
challenge your skills using our exercises.

Doing animations right

All of our animation solutions work, but let's look at them in terms of
performance. When the user leaves our browser tab, the animation will keep
running and drain the CPU. It's even worse on mobile devices, where we can
notice a decrease in performance. We'll learn how to optimize our animations for
the web browser in the next lesson, JS requestAnimationFrame - For better drawing.