We came. We saw. We Spoke.

Monday, December 20, 2010

Let it Spoke.

by Jeremy Crapsey

Editor’s Note: Spoke wingman and resident minstrel Jeremy Crapsey mushes his huskies across the frozen white north in order to bring us an early yuletide gift. Nothing says “Nadolig Llawen” quite like a warm fire and some random math.


Just in time for the holidays, a winter wonderland has descended on Spoke. Instead of making you wait until Christmas, we thought we’d let you open up your present early and see just how we went about making this wintry snow globe animation.

Read instruction manual before use:

Use HTML and JavaScript (Flash is too bulky and obtrusive) for this project. Canvas and CSS3 are not good alternatives. Why? Because, we want to support as many browsers as possible with the least amount of work.

This animation will be viewable in all JavaScript-enabled browsers. Building in only HTML and JavaScript allows all smart phones, tablet devices, and any other product that works with Internet browsers to view this animation.

Assemble this project with small and simplistic code. Then, when the holidays are over, you can remove the code easily without damaging your site.

Assembling the project

Now the fun begins. Follow this basic outline for when you create your very own winter wonderland. Note that we used tween.js

  1. Set up the scene: This is where you build your container box in HTML, setup scripts, and CSS styles for the background.


    
        
            
        
        
            

  2. Build your snowflake: Construct your snowflake object which will be reused. We realize that no two snowflakes are alike, but to keep this simple, we used an ordinary circle. To give the illusion that they are not the same, simply change the size of the circle. Each image is 15 x 15 pixels rendered as a PNG.


    var snowFlake = function(target){
        /*
            Lets create a snowflake by using a div 
            element with a background image.
        */
        var div = document.createElement("div")
            ,random = Math.random()
            ,even = Math.floor(random*(2));
            
        //default styles
        div.style.position = "absolute";
        div.style.background = "no-repeat center";
        div.style.backgroundImage="url('snow_flake01.png')";
        div.style.width = "15px";
        div.style.height = "15px";
        div.style.top = "-15px";
        
        //default settings
        div.random = random;
        div.x = 0;
        //lets have the snowflake start above the scene
        div.y = -15;
        
        //Main function used to update the
        //snow flakes position
        div.update = function(){
            div.style.left = div.x+"px";
            div.style.top = div.y+"px";
        }
        
        //Used to update the image of the
        //snowflake
        div.setImage = function(image){
            div.style.backgroundImage = "url('"+image+"')";
        }
        
        //Used to reset the posistion of the snowflake
        div.reset = function(){
            //moves the snowflake above the scene
            div.y = -15;
        }
        
        //Inserts the Div into the targeted Element
        target.appendChild(div);
    
        return div
    }
    
    

  3. The Population, randomization, and animation script: provides the three secret ingredients to create the illusion of a gentle snowfall. Let’s assign animation rules for each individual snowflake and populate it into our target element. Keep in mind that you must render the snowflakes with an aesthetically pleasing and smooth animation.


    var renderSnow = function(opt,target){
        /*
            Our “render snow” function here will
            populate the target element with snowflakes
        */
        
        for(var i = 0;i<= opt.count;i++){
            
            var  flake = new snowFlake(target)
                ,xPos = flake.x = Math.random()*(400)
                ,random = flake.random
                ,fallSpeed = opt.fallSpeed+random*(1000)
                ,driftSpeed = opt.driftSpeed+random*(1000);
                
            //Set the current snowflake's image
            flake.setImage(opt.image);
            
            /*
                We use tween.js to propagate
                the snowflake position values.
            */
            
            floatDown = new TWEEN.Tween(flake)
                .to({y:196},fallSpeed)
                //This runs the flake update command 
                //on every refresh
                .onUpdate(flake.update);
                
            floatLeft = new TWEEN.Tween(flake)
                .to({x:xPos-30},driftSpeed);
                
            floatRight = new TWEEN.Tween(flake)
                .to({x:xPos+30},driftSpeed);
            
            floatDown
                .delay(i*opt.delay)
                .onComplete(flake.reset);
            
            //animation chians
            floatLeft.chain(floatRight);
            floatRight.chain(floatLeft);
            floatDown.chain(floatDown);
            
            floatDown.start();
            //Lets mix it up a bit and 
            //randomize the start animation.
            if(Math.floor(i%2)==0){
                floatLeft.start();
            }else{
                floatRight.start();
            }
        }
    }
    
    

  4. Animation loop script: To produce the illusion of animation, loop thirty times every second.


    //Lets target our containment elements
    var frontLayer = document.getElementById("front_layer");
    var backLayer = document.getElementById("back_layer");
    
    /*
        Here we run our “render snow” methods. This allows
        us to create two separate layers of snowfall in our 
        scene.  Here you can add more snowflake layers to
        give a more "blizzard" effect.  Adjust the speed and
        density of each layer by modifying the values 
        (the larger the number the slower the speed).
    */
    
    renderSnow({
        image:"snow_flake01.png"
        ,driftSpeed:7000
        ,fallSpeed:4000
        ,count:10
        ,delay:300
    },frontLayer);
    
    renderSnow({
        image:"snow_flake03.png"
        ,driftSpeed:7000
        ,fallSpeed:10000
        ,count:20
        ,delay:500
    },backLayer);
    
    /*
            This is where the magic happens. 
            Our frame rate is set at 30fps:
    */
    (function tick(){
        /*
            Every time TWEEN.update(); is run, the values 
            of the snow flakes we assigned tweens 
            (TWEEN.Tween()) to.  It will produce the next
            values in our tween animation, and update the
            CSS positions on our snowFlake objects.
        */
        TWEEN.update();
        setTimeout(tick,1000/30);
    }());
    

Once your project is successfully assembled and thoroughly tested, all that’s left to do is sit back and enjoy it.

We are.

Merry Christmas and a very Happy New Year.


by Jeremy Crapsey

Join the conversation

Add to the conversation

Name:

Email:

URL:

Comment

Remember my personal information
Notify me of follow-up comments?

Submit the word you see below:


Next entry: Signs of life.

Previous entry: Brands Behaving Badly

Back to main