Application Overview

Last lesson we learnt about and setup our own dynamic JS driven webpage hosted on our own machine.

In this lesson we will breakdown the various functions we are performing with the all-powerful app.js file and adding a little interaction to our page.

So let's breakdown this file chunk by chunk.

1. The Global Variables

Starting at the top of the file we have the lines:

These are what's called global variables.

Variables are elements we can store data within. By writing let container; we are saying to JS that we want to create a variable called container.

A variable is something we store data [ 3, 65.342, 'hello' etc ]. By assigning a variable to data, we can access that data at a later point and perform operations and functions on it. Here, we are declaring the variable but we haven't assigned it a value.

This declaration but not assignment is very important and if we did any operations with any of these variables our website would crash because the variables have nothing in them.

These are also special variables called global variables as they are in 'global scope' which means they can be accessed from anywhere from any file that has access to our app.js file.

We include all our files in our index.html file with <script> tags. Meaning that any file included after our app.js file will have access to these variables.

2. Initialisation & Helpers

Next up is where the magic begins. This is out initialisation function, the function that starts everything up.

This function assigns values to our global variables, sets the background colours and associates our scene with the html element scene-container through the line:

Here we assign a value to our previously declared global variable container. But wait.... what is this new document variable? HTML gives our JS some inbuilt global variables we can use to attatch to the outside browser window. In this app.js file we use the inbuilt variable document here as well as the variable window later on.

It then sets up our scene through helper functions. Helper functions are just functions that wrap up similar functionality or features. This is mainly done for convenience and to keep out code well organised:

---> Cameras are setup createCamera();

---> We create our controls, which assosiates our camera with our mouse input, through createControls();

---> All the lighting creation is handled in createLights(); which lights our lovely cube, and adds to it's colour very slightly.

---> Our cube is created through createMeshes(); Which generates the data for it's 8 points (verticies), defines it's material and adds it to our scene.

---> Finally, createRenderer(); associates our scene with our browser window or 'container' and defines the gamma and pixel ratios so the final image looks correct.

Take a look and play with these functions and their variables that are defined below the init() function to see what they're really up to.

Finally the init() function sets up our render loop. Which is the logical loop that is called every frame (or tick) and keeps are application running. If we did not have this then our screen would be blank.

3. The Render Loop

The render loop is a vital part of the real-time webgl application.

What we are doing here is calling a function called setAnimationLoop() on our renderer which we have defined in the createRenderer() function as a WebGL renderer that is the same size as our conainer and is attatched to it.

The setAnimationLoop() is a little bit different to our other functions though. In it we do not pass variables (numbers, words etc) but instead pass it another function.

This is setting a callback function within the renderer variable so when the browser looks for a function to call every frame (the animation loop) it will find our function:

Which is basically a function taking () no arguments and comprised of update(); followed by render(); Which would look like this if were to define it:

The render() function is simple, it draws our scene to the screen using our camera:

The update() function is where we put all the logic we want to happen every frame; animation, input - anything that changes. Here we animate our cube:

Here the += operator just adds whatever is to the right of it to the value on its left. We could write it as mesh.rotation.z = mesh.rotation.z + 0.01 though. But that doesn't look as cool.

4. Callback Functions

I mentioned before that our render loop uses a callback function we defined in its argument list. There is more than one way of doing this though. Strictly speaking callback functions vary from language to language but in general they are functions that get called whenever something happens within our application.

They are often used for dynamic interactions or events that happen within out application.

Callback functions are what we will use to add interaction into our scene and have it change dynamically based on our input.

For this to work we will need to define callback functions for whenever we interact with out scene like moving our mouse or clicking it. We infact have been using a window callback function all this time:

So we define a function called onWindowResize() that is called by the browser every time a window resize event happens. We then define some logic inside it that changes the renderer's size to the new size - meaning our scene is updated dynamically to the new browser size.

This isn't in our application by default - try deleting these lines at the bottom of app.js, resize the browser you're using and see for yourself! The window does not update it's size to the new browser dimensions anymore :o

The function window.addEventListener() will associate our function (the 2nd parameter, onWindowResize) with the specified event (the 1st parameter, 'resize')

You can have a look at the available event listeners available here.

5. Interaction

So let's use all of this knowledge to make some nice 'n meaningful interaction in our scene.

First we will define a new callback function:

Now whenever we click in the window our console (press F12 to see it) should print 'mouse down' like this:

But this isn't very fun - let's instead do something like this:

That's more like it!

Play around with event listeners and your own interactions and see what you come up with.

Next, we will take it to the next level and make our own brush using what we've learnt here.

If you have any trouble or are curious, you can find all of the source code for this lesson here.


Learned something?

Tell a friend about this site,

Want to see more like this?

Consider supporting through the store.


Have an idea, suggestion or just want to say hi?

The please leave a comment and subscribe!