GreenSock Tutorial Overview
This tutorial provides an in-depth walkthrough of creating a starfield animation using GreenSock. You will learn how to generate stars dynamically using a for() loop and position them using Math.random(). The tutorial also covers how to manage a complex project by nesting several timelines within one parent timeline, and offers valuable insights into how to enhance animations by randomizing start times, positions, and speeds of each element.
This exercise is excerpted from Noble Desktop’s past web development training materials created in partnership with GreenSock. It is compatible with GreenSock version 2. To learn current skills in web development, check out our coding bootcamps in NYC and live online.
Note: These materials are provided to give prospective students a sense of how we structure our class exercises and supplementary materials. During the course, you will get access to the accompanying class files, live instructor demonstrations, and hands-on instruction.
Topics covered in this GreenSock tutorial:
Creating the starfield timeline within a function, Using a for() loop to dynamically generate stars, Positioning the stars, Using Math.random() to enhance the animation
Exercise Preview
Exercise Overview
This is the first in a series of exercises in which we will explore some sophisticated tweening effects and learn how to keep a complex project manageable by nesting several timelines inside one parent timeline.
Previewing the Finished Animation
To take a look at the animation we’ll be building, open up Google Chrome.
Hit Cmd–O (Mac) or Ctrl–O (Windows), navigate to Desktop > Class Files > yourname-GSAP Class > Promo Done, and double–click on index.html.
-
Watch the animation a few times to get a sense of the pacing and the interaction of the various elements. This animation consists of five timelines animating nearly 20 elements (plus all the shooting stars!) with precise timing.
Each tween controls multiple properties of each element. Without a considered strategy, configuring the HTML and CSS for this project would be overwhelming.
-
Just like we made the Burger Boy project manageable by separating the animation into panels, we will approach this project by dividing the elements into distinct timelines that we will code separately and later combine.
NOTE: We will not be creating every element of the animation. Instead, we will be focusing on the coolest effects: the starfield and the Animation Beyond Flash text that zooms in and out.
Examining the DOM & JavaScript for the Whole Project
-
In your code editor, open yourname-GSAP Class > Promo Done > index.html
We’re not going to be coding out the whole animation, but it will be helpful to review the structure of nesting timelines within timelines in the finished file.
-
Check out the following code on lines 64–131. The contents of each function have been omitted to save room, and because we are simply focusing on the structure of the file right now:
function getNobleTimeline() {
Code Omitted To Save Space
} function getStarsTimeline() {
Code Omitted To Save Space
} function getTitlesTimeline() {
Code Omitted To Save Space
} function getPoweredByTimeline() {
Code Omitted To Save Space
} function getEndTimeline() {
Code Omitted To Save Space
}
Each of these five functions have names that correspond to the section of the animation that they create a timeline for. In this exercise, we will be focusing on building the getStarsTimeline() function.
-
Check out the code that starts //build main timeline around lines 134–141:
//build main timeline mainTimeline.from($demo, 0.5, {autoAlpha:0}) .add(getNobleTimeline(), 0.5) .add("panel2", "-=1.5") .add(getStarsTimeline(), "panel2") .add(getTitlesTimeline(), "panel2") .add(getPoweredByTimeline()) .add(getEndTimeline(), "-=0.2");
Here we are using the add() method to place the timelines (each created by the functions above) into one TimelineLite called mainTimeline. The add() method has many uses (such as adding tweens, callbacks, and nested timelines).
Once all the separately-coded timelines are added to mainTimeline, we can play, restart, reverse, pause, and control mainTimeline just like any other timeline. Any given timeline can have a virtually limitless number of child tweens and timelines.
Go ahead and close index.html in your code editor.
Previewing the Finished Starfield Animation
Let’s take a quick peek at the progress we’ll be making in this exercise.
-
In a browser, open yourname-GSAP Class > Promo Starfield Done > index.html
In this animation, 50 stars move (at random positions and random intervals) across the screen from right to left. Cool!
NOTE: Although we could create the star elements with HTML and JavaScript, we will do something more interesting: using jQuery to dynamically create 50 stars within a wrapper div. This way, we could easily add more stars dynamically if needed. This workflow will be very useful when tackling a complex GSAP project.
Reviewing the Starfield DOM
-
In your code editor, open yourname-GSAP Class > Promo Starfield > index.html
NOTE: If your code editor allows you to open an entire folder (like Sublime Text does), open the entire Promo Starfield folder.
Preview index.html in a browser. There is nothing but a black rectangle so far.
Switch back to your code editor.
-
The HTML in this file is pretty lean, as you can see on lines 18–22:
<div id="demo"> <div id="flyBy" class="panel"> <div id="starfield"></div> </div> </div>
There is a demo div that holds a flyBy div (with the class of panel). Eventually the demo div will hold more panels, one for each main section of the larger animation.
Within the flyBy div there is a starfield div. We will create a function that will dynamically insert the stars into this starfield div.
-
Check out the jQuery variables on lines 29–31:
var $demo = $("#demo"), width = $demo.width(), height = $demo.height();
The jQuery object
$
demo corresponds to the wrapper for the whole animation. The two variables width and height take the width and height of the$
demo element. We will be using these numbers programmatically later in the exercise.NOTE: If you were to open up the style.css associated with this project, you would see that the height of the wrapper is 445px and the width is 500px. However, we don’t want to hard-code these numbers into the animation, because that would make our life difficult if we wanted to quickly change the proportions or completely resize the animation for different platforms.
Creating the Starfield Timeline Within a Function
Although we are only focusing on the starfield animation right now, it is eventually going to be part of a larger sequence, and we are trying to plan ahead.
By creating the starfield timeline inside a function, we will be able to keep the code neatly separated from other code and easily call the function at the exact moment when it needs to play in the parent timeline.
-
In index.html define the function and call it (it’s important to do both!):
var $demo = $("#demo"), width = $demo.width(), height = $demo.height(); function getStarsTimeline() { } getStarsTimeline();
-
Add the following variables to the getStarsTimeline() function (around line 34):
function getStarsTimeline() { var $starfield = $("#starfield"), tl = new TimelineLite(); }
We have just created a jQuery object
$
starfield (referring to the element with an ID of starfield) and established a new TimelineLite called tl inside this function.
Using a for() Loop to Dynamically Generate Stars
-
In order to dynamically generate the stars, we will use a for loop (a common piece of JavaScript code that allows us to repeat a section of code a set number of times). Add the following bold code:
function getStarsTimeline() { var $starfield = $("#starfield"), tl = new TimelineLite(); for(var i=0; i<50; i++) { console.log(i); } }
- In case you aren’t familiar with the concept of for loops, here’s a quick explanation:
- This for loop will repeat the same block of code 50 times.
- We created a variable named i, which in this case is known as a counter variable.
- We also specified that the initial value of i is zero.
- Every time the code runs, it will check to see if the value of i is less than 50. If that is true, the code inside the loop will execute.
- After the code executes, i will increment by 1.
We want 50 stars, so we have set i<50. At this point, we are just logging things in the Console to make sure it’s all working.
Save the file and preview it in Chrome, (we’ll use the DevTools’ Console tab).
-
Hit Cmd–Opt–J (Mac) or Ctrl–Shift–J (Windows) to bring up the Console.
Notice the numbers 0 through 49 in the Console—good, the for loop is working as expected. If you reload the page, the numbers 0 through 49 will appear again.
We recommend leaving the page open in Chrome so you can just reload the page while you work.
-
Return to your code editor and replace the console.log as follows:
function getStarsTimeline() { var $starfield = $("#starfield"), tl = new TimelineLite(); for(var i=0; i<50; i++) { var element = $("<div class='star'></div>").appendTo($starfield); } }
This semi-magical line of jQuery code will create a new div element with the class of star (singular!) and insert it into the starfield div. The newly created div will be associated with the variable element. The for loop will be responsible for adding 50 instances of star into the starfield div.
-
Don’t worry if you don’t completely understand the syntax of this jQuery code; let’s check out the results in the browser. Save the file and reload the browser.
The change is very hard to notice: in the top-left corner of the black rectangle, there is a single star, which looks like a few gray and white pixels. You might be asking, why aren’t there 50 of them? Let’s take a closer look at the code.
Ctrl–click (Mac) or Right–click (Windows) on the star and select Inspect to view the page’s code in the DevTools.
-
Use the gray arrows to expand the flyBy div and the starfield div (if not already expanded). You will then see the 50 divs named star nested inside that div.
The reason we can’t see all 50 stars is that they all have the same top-left coordinate. We can fix that in a moment, but it’s good that we can use Inspect to check that all 50 divs are indeed present.
Return to your code editor and open Promo Starfield > css > style.css
-
Check out the following code on lines 19–24. Each star div appears the way it does because of this CSS styling:
.star { position:absolute; width:27px; height:4px; background:url(../img/star.png); }
Positioning the Stars
Let’s position the stars so they’re not all in the same place. Switch back to index.html in your code editor.
-
Let’s use the set() method to position the 50 stars 10 pixels apart from each other. Add the following bold code:
function getStarsTimeline() { var $starfield = $("#starfield"), tl = new TimelineLite(); for(var i=0; i<50; i++) { var element = $("<div class='star'></div>").appendTo($starfield); TweenLite.set(element, {y:i * 10}); } }
Save the file and reload the browser. Excellent, the stars are now stacked on top of each other, spaced 10 pixels apart. Let’s make the spacing less uniform.
-
Return to your code editor and make the following change to the set() method you just added:
for(var i=0; i<50; i++) { var element = $("<div class='star'></div>").appendTo($starfield); TweenLite.set(element, {y:Math.random()*height}); }
Math.random() will produce a random number between 0 and 1. We are multiplying it by the height variable, which is equal to the height of the black rectangle wrapper.
Save the file and reload the browser. The random arrangement is much better!
Reload the page a few times and notice that with each reload, the stars are positioned differently. Cool!
Next, let’s make the stars move from right to left. Return to your code editor.
-
As a first step, position the stars at the right side of the panel by adding the following bold code:
TweenLite.set(element, {y:Math.random()*height, x:width});
-
Save the file and reload the browser.
The x:width code means that the left edge of each star is set to the width of the panel, so the stars are sitting right outside the rectangular frame.
Let’s create the tweens for the shooting star effect!
-
Return to your code editor and add the following bold code:
for(var i=0; i<50; i++) { var element = $("<div class='star'></div>").appendTo($starfield); TweenLite.set(element, {y:Math.random()*height, x:width}); tl.to(element, 0.5, {x:-50, ease:Linear.easeNone}); }
Each tween will have a duration of 0.5 seconds and each star will move to a position of x:–50 (which will be out of the frame, on the left-hand side).
Save the file and reload the browser. The animation is working, but it’s dull to watch each tween happen sequentially. Let’s make the pace more exciting.
-
Return to your code editor and add the following bold code:
tl.to(element, 0.5, {x:-50, ease:Linear.easeNone}, 0);
Save the file and reload the browser. The quicker speed is certainly an improvement over the dull one-by-one pace, but the animation still doesn’t look very natural with all 50 stars moving at once.
Using Math.Random() to Enhance the Animation
Let’s use Math.random() again, this time to randomize the start times.
-
Return to your code editor and make the following change to the to() method:
tl.to(element, 0.5, {x:-50, ease:Linear.easeNone}, Math.random());
Save the file and reload the browser. Because Math.random() produces a number between 0 and 1, the stars animate in a pleasingly random way over the course of one second. It’s good, but a little too quick.
-
Return to your code editor and in the to() method, add the following code that makes all 50 star tweens happen within the course of three seconds:
tl.to(element, 0.5, {x:-50, ease:Linear.easeNone}, Math.random()*3);
Save the file and reload the browser. The pacing of these spread-out start times seems much better. Let’s also try randomizing the speed of each star’s tween.
-
Return to your code editor and make the following change to the to() method:
tl.to(element,
Math.random()*
0.5,
{x:-50, ease:Linear.easeNone},
Math.random()*3);
Save the file and reload the browser. Looking good.
Hiding the Overflow
This animation is almost finished—all we need to do is hide the off-stage starting and ending position of each star.
Return to your code editor and open Promo Starfield > css > style.css
-
In the rule for #demo add the following bold code (around line 13):
#demo { position:relative; width:500px; height:445px; background-color:#000; margin:auto; overflow:hidden; }
-
Save the file and reload the browser. Excellent!
We have dynamically generated 50 stars and made the animation have more depth and naturalism by randomizing the start time, the position, and the speed of each star element.