Can't wait for winter? Love how pretty falling snow is?
Now you can add it to your webpage and imagine you're looking into a winter wonderland!
Alternatively, this code can also be found on github.
Let's start by setting up your webpage to use the CreateJS framework.
<!doctype html> <html> <head> <meta charset="utf-8" />; <title>Snowy Tutorial</title> <link href="main.css" rel="stylesheet" /> <script src="http://code.createjs.com/createjs-2013.12.12.min.js"></script> </head> <body id="demo"> </body> </html>
You'll need to use the script tag within the head tag to link to the CreateJS framework. Here, we're using the 2013.12.12 release of CreateJS found here.
We've given the body tag an id of demo for an optional CSS extra after this tutorial. If you'd prefer not to use css, make sure you add a black background to your body tag so that you can see the white snowflakes. It would look something like this:
<body bgcolor="#000000"> </body>
Next, let's create the canvas to draw on in HTML and link it to our JavaScript.
The HTML code goes in between the body tags we set up in Step 2.
<canvas id="myCanvas">alternative content</canvas> <script> var canvas = document.getElementById("myCanvas"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; </script>
It is very important to set up an id (here, id="myCanvas") so that the canvas element can be called in other locations.
You'll notice that we set up the length and width of the canvas using JavaScript. This is so that we can use the window.innerWidth and window.innerHeight properties to make the animation full screen on any window size after using document.getElementById method to access the canvas element.
In order to "draw" on our canvas, we need to set up our Javascript within the head tags and within another script tag. We will use window.addEventListener with a "load" type to ensure that the window has loaded before the script runs. The "listener", in this case init, is a function that we will create next to run our JavaScript.
<script> window.addEventListener("load", init); function init() { // HERE WE ARE OPENING OUR "init" FUNCTION var stage = new createjs.Stage("myCanvas"); } </script>
In CreateJS, we can create a new Stage class that basically sits within the HTML canvas, allowing us to render to it. It calls the id of our canvas, myCanvas.
Of Note: all specifically CreateJS classes must be predicated with createjs. in order to be used.
Now we essentially have a stage for our canvas, but we haven't put anything on it yet. We need to add an object to the canvas in order to see anything.
We first use a setInterval method to tell the page to run the snowBegin function every 200 milliseconds. This is how multiple snowflakes are generated.
Also, since we're calling snowBegin, we should probably create it somewhere nearby:
setInterval(snowBegin, 200); function snowBegin() { // HERE WE ARE OPENING OUR "snowBegin" FUNCTION
Now let's add an image of a pretty snowflake to our stage, still within our snowBegin function. I have used the snowflake image seen in this page's header, but you may feel free to use any snowflake image of your own. Make sure you resize the image appropriately before uploading it.
We used the Bitmap class to create an image object and named it "snowflake". We've also added an x value that will prove useful later on. However, nothing show up just yet. First, we will create a Container class and place our Bitmap object into it using the addChild method; this is all still within our script tags.
var snowflake = new createjs.Bitmap("snowflakeS.png"); snowflake.x = 25; var container = new createjs.Container(); container.addChild(snowflake);
We're now essentially working with an invisible Bitmap in an invisible Container on an invisible Stage as part of an invisible canvas. Don't worry, things will start to show up soon.
But just before they do, we want to initialize an x registration point value for our container variable.
container.x = Math.random()*window.innerWidth;
We want our snowflakes to appear haphazardly across the top of our page, just like real snow, so we assign the x registration point a value of Math.random()*window.innerWidth;. This will randomly assign the first position of our snowflake somewhere along the horizontal at the top of our page.
Before we start seeing things, we have one more variable to set up. We've called it duration, and it will be used in the next Step to determine the speed of our tween animation.
var duration = Math.random()*1000+1000;
Again, we have randomized it using Math.random(), but we have multiplied by 1000 and added 1000 to make sure none of the snowflakes move unnaturally fast.
Finally, let's start seeing some stuff!
In the following block of code, we will use the Tween class to tween animate the movement of our snowflake back and forth from an x registration point of 0 pixels to an x registration point of 25 pixels. These pixel measurements are relative to the starting position of the Container variable, since we've placed the snowflake into the container.
createjs.Tween.get(snowflake, {loop:true}) .to({x:0, alpha:1}, createjs.Ease.quadInOut) .wait(15) .to({x:25, alpha:1}, duration, createjs.Ease.quadInOut) .wait(15) .to({x:0, alpha:1}, duration, createjs.Ease.quadInOut); stage.addChild(container);
You may have noticed we also used the addChild method again; this time we've added the container, with the snowflake object in it, to the stage. We've also added a loop:true configuration property to our Tween to have this animation run continuously.
We have also added an Ease class with a quadInOut method to have the snowflake travel quadratically rather than linearly.
What's that? Not seeing anything yet? That's because we haven't told the stage to update itself with all of the information we just assigned to it. That's at the bottom of this block of code:
createjs.Tween.get(container, {loop:true}) .to({y:window.innerHeight}, 10000, createjs.Ease.BackOut); createjs.Ticker.on("tick", stage).setInterval(5); } // HERE WE ARE CLOSING OUR "snowBegin" FUNCTION
Here, we are continuously tweening our container at the same time as the object within it, snowflake, has it's own continuous tween pattern. This time, we're telling the container to animate from the default y registration point of 0 to the new y registration point of the height of the screen, aka the bottom of the screen, for 10000 milliseconds. We've added an Ease class again with a backOut method to have the snowflake have a soft landing at the bottom of the page. This Ease is a personal preference and is not necessary.
Now, to update! Finally. We've added a Ticker class with a "tick" type and have the stage as the listener. setInterval was added to toggle how fast the stage updated with every tick, here we have chosen 5 milliseconds to try to smooth the tween on faster machines. Slower machines will require a slower interval and will override this command.
If you've been keeping up and closing all of your functions as you go along, well done, it looks pretty good! ...But there's one more thing before we go!
If you're getting a blank screen or errors in the console, stick with us! You're almost there!
Notice how if you watch your animation for a while, the snow starts to pile up? To avoid that, we're going to add a call method to our container tween so it now looks like this:
createjs.Tween.get(container, {loop:true}) .to({y:window.innerHeight}, 10000, createjs.Ease.BackOut) .call(removeContainer);
Of course, this means that we're now going to make a function called removeContainer underneath our now closed snowBegin function but still within the init function. This will remove each snowflake after it passes the bottom of the page height (i.e. after the tween of each snowflake finishes).
function removeContainer(e) { stage.removeChild(e.target); }
Finally, at long last, we're going to close our init function we opened so long ago. Double-check that you're still working within the script HTML tags, or else this won't work!
} // HERE WE ARE CLOSING OUR "init" FUNCTION
If you would like your CSS to reflect a plain black background, simply use this:
#demo { background-color: #000000; }
However, this isn't very exciting. You can basically put anything in your body tag, including the code to an entire webpage, and have the snow fall overtop. However, there are a few key stipulations:
Place all of your content between the closing script tag and the closing body tag of your document. Here is a snippet as an example:
<body id="demo"> <canvas id="myCanvas">alternative content</canvas> <script> var canvas = document.getElementById("myCanvas"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; </script> <!-- ALL OF YOUR CONTENT GOES HERE --> </body>
You may have noticed that this places your canvas at the top of the page, with your content underneath it. This is where your CSS comes in. It should look something like this:
#demo { z-index: 1; position: absolute; } canvas { position: absolute; z-index: 2; }
The z-index will arrange the "layers", or elements, of your document in the order you want. A higher z-index translates to a higher viewing priority.
Now just put any other content you want in the body, and providing it is not content on a white background, VOILA! You have a beautiful snow-covered page. Now, where's that hot cocoa I was getting to...
Here's what this page looks like with snow at the top! Click here to check your code!
This tutorial was created by Andrea Kereliuk, 2014. Prettifying the pre tags courtesy of prettify google code.