Wednesday 16 December 2015

Web Tutorial: A Christmas Animation (Part 2/4)

We have a snowy animated background. Cool! But what's a background without a skyline? That's right. We're going to make a skyline out of simple rectangular blocks.

First, revert your CSS for the main_wrapper and snow_wrapper divs to the previous settings. This will give you a better view of what's going on.

Now add the CSS class house.
            #main_wrapper
            {
                margin-left:auto;
                margin-right:auto;
                margin-top:5%;
                margin-bottom:200px;
                width:400px;
                height:400px;
                background-color:#000044;
                position:relative;
                overflow:visible;
            }   

            .house
            {
                background-color:#000000;
                width:50px;
                height:300px;
                border:0px solid #FFFFFF;
                float:left;
                margin-top:400px;
                position:relative;
                z-index:10;
                transition:margin-top 2s;
                -webkit-transition:margin-top 2s;
            }

            .snow_wrapper
            {
                width:600px;
                height:600px;
                position:absolute;
                z-index:10;
                margin-top:-200px;
                border:1px solid #00FFFF;
            }

Here's what the CSS does...
- background-color:#000000 makes the block black. A good color for what's essentially supposed to be a silhouette.
- width:50px, height:300px defines the dimensions of each building block.
- float:left ensures that each div with the class house, aligns neatly to the left side of main_wrapper.
- margin-top:400px pushes all the blocks down, past the height of the main_wrapper div. But since the overflow property of the main_wrapper div is set to visible, you can still see them at the moment!
- transition:margin-top 2s specifies that any change involving the margin-top property of the div will be tweened over 2 seconds.

Now that the CSS is defined, I want you to do this to your HTML. And change the body's background color to white, so you can see better.
    <body onload="play();" style="background-color:#FFFFFF;">
        <div id="main_wrapper">
            <div id="spinright" class="snow_wrapper">

            </div>

            <div id="spinleft" class="snow_wrapper">
           
            </div>

            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
        </div>


Do you see that all the blocks are aligned like this? Looks like one solid black block, doesn't it?


Great. Now we're going to add the JavaScript to animate them. Of course, we're going to add raisehouses() function to the play() function. So as soon as the page is loaded, snowflakes() runs first, followed by raisehouses()!
            function raisehouses()
            {

            }


            function play()
            {
                snowflakes(100);
                raisehouses();
            }
</div>

This is the JavaScript.
<div class="post_box code">
            function raisehouses()
            {
                var houses=document.getElementsByClassName("house");

                for (var i=0;i<houses.length;i++)
                {
                    createwindows(houses[i]);
                    houses[i].style.marginTop=generaterandomno(100,200)+"px";
                }

            }

            function play()
            {
                snowflakes(100);
                raisehouses();
            }


Firstly, you get all elements that use the CSS class house, ie. all the black black , and put their id in an array. Next, you use a For loop to traverse the array. Each of these houses will have their margin-top property set with a random value, so that they all spring up and form a randomly distributed skyline, made of buildings with various heights.

Then the createwindows() function is run for each block. Here's the JavaScript for it...
            function createwindows(varobj)
            {
                var table="";

                table+="<table style=\"width:80%;margin-left:auto;margin-right:auto;margin-top:10px;\" cellspacing=\"5\">";
                for (var i=0;i<generaterandomno(2,8);i++)
                {
                    table+="<tr>";
                    table+="<td style=\"background-color:#"+(generaterandomno(0,2)==1?"000000":"FFFF00")+"\">&nbsp;</td>";
                    table+="<td style=\"background-color:#"+(generaterandomno(0,2)==1?"000000":"FFFF00")+"\">&nbsp;</td>";
                    table+="</tr>";                   
                }
                table+="</table>";

                varobj.innerHTML=table;
            }


            function raisehouses()
            {
                var houses=document.getElementsByClassName("house");

                for (var i=0;i<houses.length;i++)
                {
                    createwindows(houses[i]);
                    houses[i].style.marginTop=generaterandomno(100,200)+"px";
                }
            }

            function play()
            {
                snowflakes(100);
                raisehouses();
            }


The createwindows() function generates a HTML table with with 2 columns and between 2 to 8 rows, again using the generaterandomno() function. These are the "windows" of the buildings. Of course, not all windows will be lit up. So each window is given a 1-in-3 chance of not being lit up .ie, with a yellow background. You may wish to adjust the color or the random values as you see fit. That particular block's innerHTML property is then set to the HTML table.

Now that's what it does.


Set the overflow property of your main_wrapper CSS class back to hidden and the border property of the snow_wrapper CSS class back to 0px.
            #main_wrapper
            {
                margin-left:auto;
                margin-right:auto;
                margin-top:5%;
                margin-bottom:200px;
                width:400px;
                height:400px;
                background-color:#000044;
                position:relative;
                overflow:hidden;
            }  

            .house
            {
                background-color:#000000;
                width:50px;
                height:300px;
                border:0px solid #FFFFFF;
                float:left;
                margin-top:400px;
                position:relative;
                z-index:10;
                transition:margin-top 2s;
                -webkit-transition:margin-top 2s;
            }

            .snow_wrapper
            {
                width:600px;
                height:600px;
                position:absolute;
                z-index:10;
                margin-top:-200px;
                border:0px solid #00FFFF;
            }


Presto!



What's wrong with this picture?

Well, you'll notice that the snowflakes are all falling behind the buildings. This isn't wrong per se, but we can do better.

Try moving the code segment.
            <div id="spinright" class="snow_wrapper">

            </div>

            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>
            <div class="house"></div>

            <div id="spinleft" class="snow_wrapper">
          
            </div>


Run your code again in the browser. See that some snowflakes are falling in front of the buildings, and some behind? That's because the buildings and the spinright and spinleft divs (which hold the snowflakes) have all had their z-index properties set to 10. So that being equal, the browser just renders the items according to their sequence in the HTML, ie. spinright div, building blocks, spinleft div.




Next

The next piece of the puzzle - Santa himself.


No comments:

Post a Comment