Wednesday 3 February 2016

Web Tutorial: Year of the Monkey Countdown

Great gibberin' gorillas! It's 2016, and the Year of the Monkey is due to arrive in a week or so.

What that means for us is that there'll be a web tutorial. Today, I will show you how to make a JavaScript-enabled countdown. More specifically, a countdown to Chinese New Year. This will involve JavaScript's timer functions and use of the Javascript Date object. If either (or both) of these don't seem familiar to you, I'd recommend a little reading up before we proceed.

More on JavaScript Timer functions. (http://www.w3schools.com/js/js_timing.asp)
More on the Date object. (http://www.w3schools.com/js/js_dates.asp)

Today's objective

Put up a pop-up on the screen that has a ticking countdown to Chinese New Year, and at the stroke of midnight, set off an animation. So without further ado, let's get the HTML in order. This part is similar, almost identical, to the Lightbox Effect and LKY's Memorial. Here, we're going to set the background color of your body to a dark blue just to bring out the contrast. The Lorem Ipsum text is just to help illustrate the effects of the overlay.

<html>
    <head>
        <title>CNY 2016</title>

        <style>
            #cny_overlay
            {
                top:0px;
                left:0px;
                width:100%;
                height:100%;
                position:fixed;
                background-color:rgba(200,200,200,0.2);
            }

            #cny_container
            {
                width:80%;
                height:80%;
                top:10%;
                left:10%;
                border-radius:20px;
                position:absolute;
                background-color:rgba(200,200,200,1);
            }
        </style>
    </head>

    <body style="background-color:#000044">
        <div id="cny_overlay">
            <div id="cny_container">

            </div>
        </div>

        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </body>
</html>




Now for a timer display

Month, Day, Hour, Minute and Seconds are all represented by two digits. Each digit is represented by a box. That box is a div, styled using the digitbox class.

These divs are in turn encapsulated within an outer div with an id of time_wrapper.

The smallbox class is purely cosmetic.

Add the HTML and CSS shown here.
<html>
    <head>
        <title>CNY 2016</title>

        <style>
            #cny_overlay
            {
                top:0px;
                left:0px;
                width:100%;
                height:100%;
                position:fixed;
                background-color:rgba(200,200,200,0.2);
            }

            #cny_container
            {
                width:80%;
                height:80%;
                top:10%;
                left:10%;
                border-radius:20px;
                position:absolute;
                background-color:rgba(200,200,200,1);
            }

            #time_wrapper
            {
                width:330px;
                margin:5% auto 0 auto;
                text-align:center;
                font-family:verdana;
                font-weight:bold;
                font-size:30px;
                color:rgba(0,0,0,1);
                -webkit-transition: all 1.5s;
                -webkit-transform:perspective(500px) rotateX(0deg);
                -webkit-transform-origin:50% 50%;
                -webkit-perspective-origin:50% 100%;
                transition: all 1.5s;
                transform:perspective(500px) rotateX(0deg);
                transform-origin:50% 50%;
                perspective-origin:50% 100%;
            }

            .digitbox
            {
                width:30px;
                height:60px;
                font-size:40px;
                float:left;
                text-align:center;
            }

            .smallbox
            {
                width:60px;
                height:60px;
                font-size:15px;
                text-align:center;
                float:left;
            }
        </style>
    </head>

    <body style="background-color:#000044">
        <div id="cny_overlay">
            <div id="cny_container">
                <div id="time_wrapper">
                    <div id="day_wrapper1" class="digitbox">0</div>
                    <div id="day_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="hour_wrapper1" class="digitbox">0</div>
                    <div id="hour_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="minute_wrapper1" class="digitbox">0</div>
                    <div id="minute_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="second_wrapper1" class="digitbox">0</div>
                    <div id="second_wrapper2" class="digitbox">0</div>
                    <br style="clear:both"/>
                    <div id="days" class="smallbox">days</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="hours" class="smallbox">hours</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="minutes" class="smallbox">mins</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="seconds" class="smallbox">secs</div>
                    <br style="clear:both"/>
                    to the Year of the Monkey
                </div>
            </div>
        </div>

        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </body>
</html>


This is the result. As you can see, it aligns so neatly because each digitbox-styled div has a width of 30 pixels. This adds up perfectly because there are two of these to each smallbox-styled div, with a width of 60 pixels. The HTML and CSS here are self-explanatory, I hope. And even if not, well, they're not the focus of this web tutorial today. The point of all this styling is just to make shit look pretty. But the important thing is for it to work!

So take a look at what you have so far.


Updating the timer

Now it's time to tinker with the logic behind the digital display. Your timer display is great, but it's all 0s. Surely that can't be right. We need to calculate how much time there is remaining from now to Chinese New Year.

Modify your HTML like so. This ensures that the initialize() function is called when the page loads.
<body onload="initialize();" style="background-color:#000044">


And then add the script.
        <style>
            #cny_overlay
            {
                top:0px;
                left:0px;
                width:100%;
                height:100%;
                position:fixed;
                background-color:rgba(200,200,200,0.2);
            }

            #cny_container
            {
                width:80%;
                height:80%;
                top:10%;
                left:10%;
                border-radius:20px;
                position:absolute;
                background-color:rgba(200,200,200,1);
            }

            #time_wrapper
            {
                width:330px;
                margin:5% auto 0 auto;
                text-align:center;
                font-family:verdana;
                font-weight:bold;
                font-size:30px;
                color:rgba(0,0,0,1);
                -webkit-transition: all 1.5s;
                -webkit-transform:perspective(500px) rotateX(0deg);
                -webkit-transform-origin:50% 50%;
                -webkit-perspective-origin:50% 100%;
                transition: all 1.5s;
                transform:perspective(500px) rotateX(0deg);
                transform-origin:50% 50%;
                perspective-origin:50% 100%;
            }

            .digitbox
            {
                width:30px;
                height:60px;
                font-size:40px;
                float:left;
                text-align:center;
            }

            .smallbox
            {
                width:60px;
                height:60px;
                font-size:15px;
                text-align:center;
                float:left;
            }
        </style>

        <script>
            var countdowntimer;
            var cnydate=new Date(2016,1,9,8,0,0,0);
            var nowdate=new Date();
            var ms;

            var trembletimer;

            function initialize()
            {

            }
        </script>
    </head>


What this code does

Firstly, we define the date for Chinese New Year, which is 8th February, 2016, and assign it to a variable cnydate. Then we get the date for right now and assign it to a variable nowdate. So now cnydate holds the total number of milliseconds from 1st January, 1970 to Chinese New Year, and nowdate holds the total number of milliseconds since 1st January, 1970. ms is a global variable used to keep track of the number of milliseconds left to Chinese New Year.

The countdowntimer and trembletimer variables are used in the animation later. We'll get to that in a bit, promise!

Processing this information...

Now we're going to use that information in the function initialize().

            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {

                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }


If cnydate is greater than nowdate, that means there's still time before Chinese New Year. So the variable ms is declared, and assigned to it is the value of cnydate minus nowdate.

If ms is more than 0, we update the timer display. If not, Chinese New Year has arrived and we do a different animation! And this is, of course, the start_animation() function which we'll elaborate on later. But for now, let's dissect the variable ms. ms now represents the number of milliseconds from now to Chinese New Year.

There are 1000 milliseconds in 1 second.
There are 60 seconds in 1 minute.
There are 60 minutes in 1 hour.
And there are 24 hours in 1 day.

So we start off by deriving the approximate number of seconds in ms, and assign it to the variable s.

            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {
                    s=Math.floor(ms/1000);
                    m=(s-(s%60))/60;
                    s=s%60;   
                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }


Then we derive the number of minutes in s, and assign it to the variable m. This is calculated by taking the remainder of s divided by 60, subtracting that value from s, and then dividing the result by 60. Then we take s, divide it by 60, and get the remainder. So if s is 1000, there would be 16 minutes and 40 seconds.

Do the same for hour (h) and day(d)

            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {
                    s=Math.floor(ms/1000);
                    m=(s-(s%60))/60;
                    s=s%60;
                    h=(m-(m%60))/60;
                    m=m%60;
                    d=(h-(h%24))/24;
                    h=h%24;
                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }


Now we need to update the timer display with the values derived. Again, we're going to exploit the humble Modulus here.

Let's assume the value of h is 21. So we need to put "2" in the day_wrapper1 div and "1" in the day_wrapper2 div. How do we calculate this?

            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {
                    s=Math.floor(ms/1000);
                    m=(s-(s%60))/60;
                    s=s%60;
                    h=(m-(m%60))/60;
                    m=m%60;
                    d=(h-(h%24))/24;
                    h=h%24;

                    document.getElementById("hour_wrapper1").innerHTML=(h-(h%10))/10;
                    document.getElementById("hour_wrapper2").innerHTML=h%10;
                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }


If h is 14, for example, the first digit would be (14-(14%10))=1. And the second digit would be 14%10=4.

Do the same for the others!
            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {
                    s=Math.floor(ms/1000);
                    m=(s-(s%60))/60;
                    s=s%60;
                    h=(m-(m%60))/60;
                    m=m%60;
                    d=(h-(h%24))/24;
                    h=h%24;

                    document.getElementById("day_wrapper1").innerHTML=(d-(d%10))/10;
                    document.getElementById("day_wrapper2").innerHTML=d%10;
                    document.getElementById("hour_wrapper1").innerHTML=(h-(h%10))/10;
                    document.getElementById("hour_wrapper2").innerHTML=h%10;
                    document.getElementById("minute_wrapper1").innerHTML=(m-(m%10))/10;
                    document.getElementById("minute_wrapper2").innerHTML=m%10;
                    document.getElementById("second_wrapper1").innerHTML=(s-(s%10))/10;
                    document.getElementById("second_wrapper2").innerHTML=s%10;   
                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }


Here you go.


Animating the timer

We could run all these calculations every second from this point on, and repopulate the values. But this just feels clunky and highly unprofessional. So what we'll do it update the seconds display every second. And when it hits "00", we change it to "59" and update the minutes display. And when the minutes display hits "00", we change that to "59" and update the hours display. That is the timer_decrement() function, set in motion by the timer variable countdowntimer, which, in turn, was declared at the beginning of the JavaScript segment. Remember that?

This could be done with a whole mess of nested If-else statements, but again, that's clunky. We'll make a recursive function instead!

What's a recursive function? Find out at this link! (https://en.wikipedia.org/wiki/Recursive_function)

You'll notice that there are two parameters in the decrement_timer() function - vartype and varno. vartype is the unit that is being decremented - seconds, minutes, hours or days. varno is the digit that is being decremented. Naturally, we start off with vartype being "seconds" and varno being "2".
            function initialize()
            {
                var s,h,m,d;
                var ms=cnydate-nowdate;               

                if (ms>0)
                {
                    s=Math.floor(ms/1000);
                    m=(s-(s%60))/60;
                    s=s%60;
                    h=(m-(m%60))/60;
                    m=m%60;
                    d=(h-(h%24))/24;
                    h=h%24;

                    document.getElementById("day_wrapper1").innerHTML=(d-(d%10))/10;
                    document.getElementById("day_wrapper2").innerHTML=d%10;
                    document.getElementById("hour_wrapper1").innerHTML=(h-(h%10))/10;
                    document.getElementById("hour_wrapper2").innerHTML=h%10;
                    document.getElementById("minute_wrapper1").innerHTML=(m-(m%10))/10;
                    document.getElementById("minute_wrapper2").innerHTML=m%10;
                    document.getElementById("second_wrapper1").innerHTML=(s-(s%10))/10;
                    document.getElementById("second_wrapper2").innerHTML=s%10;   
           
                    countdowntimer=setInterval(function(){timer_decrement("second",2);},1000);
                }
                else
                {
                    setTimeout(function(){start_animation();},2000);
                }
            }

            function timer_decrement(vartype,varno)
            {
               
            }


The timer_decrement() function begins with an If-else statement. First, we decrement ms by 1000 (1 second) check if ms is still more than 0. If not, we set all of the timer display to "00" and fire off start_animation(). But if there's still time, we keep decrementing.
            function timer_decrement(vartype,varno)
            {
                ms-=1000;

                if (ms<=0)
                {
                    var digitboxes=[],smallboxes=[];
                    digitboxes=document.getElementsByClassName("digitbox");

                    for (i=0;i<digitboxes.length;i++)
                    {
                        digitboxes[i].innerHTML="0";
                    }

                    setTimeout(function(){start_animation();},2000);
                }
                else
                {

                }
            }


Here, we create a variable wrapper and use vartype and varno to get the appropriate div. If the value hasn't hit "0", we simply decrement it and move on. If the value has hit "0", then we need to check if it's the first or second digit.

If it's the first digit, we set the value to "5" (which is the first digit of "59"), and the function calls itself, this time with vartype set to "minutes" and varno set to "2".

If it's the second digit, we set the value to "9" (which is the second digit of "59"), and the function calls itself, this time with vartype set to "seconds" and varno set to "1".
            function timer_decrement(vartype,varno)
            {
                ms-=1000;

                if (ms<=0)
                {
                    var digitboxes=[],smallboxes=[];
                    digitboxes=document.getElementsByClassName("digitbox");

                    for (i=0;i<digitboxes.length;i++)
                    {
                        digitboxes[i].innerHTML="0";
                    }

                    setTimeout(function(){start_animation();},2000);
                }
                else
                {
                    var wrapper;

                    if (vartype=="second")
                    {
                        wrapper=document.getElementById(vartype+"_wrapper"+varno);

                        if (wrapper.innerHTML=="0")
                        {
                            if (varno==1)
                            {
                                wrapper.innerHTML="5";
                                timer_decrement("minute",2);
                            }

                            if (varno==2)
                            {
                                wrapper.innerHTML="9";
                                timer_decrement("second",1);
                            }
                        }
                        else
                        {
                            wrapper.innerHTML=parseInt(wrapper.innerHTML)-1;
                        }
                    }
                }


Phew. Need some time to digest that? Well, when you're done, repeat for the rest.

            function timer_decrement(vartype,varno)
            {
                ms-=1000;

                if (ms<=0)
                {
                    var digitboxes=[],smallboxes=[];
                    digitboxes=document.getElementsByClassName("digitbox");

                    for (i=0;i<digitboxes.length;i++)
                    {
                        digitboxes[i].innerHTML="0";
                    }

                    setTimeout(function(){start_animation();},2000);
                }
                else
                {
                    var wrapper;

                    if (vartype=="second")
                    {
                        wrapper=document.getElementById(vartype+"_wrapper"+varno);

                        if (wrapper.innerHTML=="0")
                        {
                            if (varno==1)
                            {
                                wrapper.innerHTML="5";
                                timer_decrement("minute",2);
                            }

                            if (varno==2)
                            {
                                wrapper.innerHTML="9";
                                timer_decrement("second",1);
                            }
                        }
                        else
                        {
                            wrapper.innerHTML=parseInt(wrapper.innerHTML)-1;
                        }
                    }

                    if (vartype=="minute")
                    {
                        wrapper=document.getElementById(vartype+"_wrapper"+varno);

                        if (wrapper.innerHTML=="0")
                        {
                            if (varno==1)
                            {
                                wrapper.innerHTML="5";
                                timer_decrement("hour",2);
                            }

                            if (varno==2)
                            {
                                wrapper.innerHTML="9";
                                timer_decrement("minute",1);
                            }
                        }
                        else
                        {
                            wrapper.innerHTML=parseInt(wrapper.innerHTML)-1;
                        }
                    }

                    if (vartype=="hour")
                    {
                        wrapper=document.getElementById(vartype+"_wrapper"+varno);

                        if (wrapper.innerHTML=="0")
                        {
                            if (varno==1)
                            {
                                wrapper.innerHTML="2";
                                timer_decrement("day",2);
                            }

                            if (varno==2)
                            {
                                wrapper.innerHTML="3";
                                timer_decrement("hour",1);
                            }
                        }
                        else
                        {
                            wrapper.innerHTML=parseInt(wrapper.innerHTML)-1;
                        }
                    }

                    if (vartype=="day")
                    {
                        wrapper=document.getElementById(vartype+"_wrapper"+varno);

                        if (wrapper.innerHTML=="0")
                        {
                            if (varno==2)
                            {
                                wrapper.innerHTML="9";
                                timer_decrement("day",1);
                            }
                        }
                        else
                        {
                            wrapper.innerHTML=parseInt(wrapper.innerHTML)-1;
                        }
                    }
                }
            }


Refresh! Does your timer display move?

Now for the animation!

So when Chinese New Year arrives, start_animation() is fired off. Let's fill in the code for that!
            function start_animation()
            {
                clearInterval(countdowntimer);

                document.getElementById("time_wrapper").style.transform="perspective(500px) rotateX(360deg)";
                document.getElementById("time_wrapper").style.color="rgba(0,0,0,0)";
            }


Here, we begin by stopping the countdowntimer. The next two lines animates the timer display by "flipping" it, and at the same time sets the color to transparent. And then we time the display to disappear at 1500 milliseconds later. We'll test this later.

Now, we're doing to create another div in the HTML, and call it year_wrapper. This basically displays "2016" in huge letters, with a monkey's head in place of "0". Not terribly original, I know. Bite me.

This is the HTML.
            <div id="cny_container">
                <div id="year_wrapper">
                    <div class="yeardigit_wrapper">2</div>
                    <div id="monkey_wrapper">
                        <div class="monkey monkey_face" style="width:90px;height:90px;margin-left:20px;margin-top:30px;"></div>
                        <div class="monkey monkey_face" style="width:90px;height:90px;margin-left:90px;margin-top:30px;"></div>
                        <div class="monkey monkey_face" style="width:140px;height:140px;margin-left:30px;margin-top:50px;"></div>
                        <div id="monkey_brow1" class="monkey"></div>
                        <div id="monkey_brow2" class="monkey"></div>
                        <div id="monkey_eye1" class="monkey"></div>
                        <div id="monkey_eye2" class="monkey"></div>
                        <div id="monkey_nostril1" class="monkey"></div>
                        <div id="monkey_nostril2" class="monkey"></div>
                        <div id="monkey_lip" class="monkey"></div>   
                    </div>
                    <div class="yeardigit_wrapper">1</div>
                    <div class="yeardigit_wrapper">6</div>
                </div>
                <div id="message_wrapper">
                    T___T wishes you a happy and prosperous CNY!
                </div>

                <div id="time_wrapper" onclick="start_animation();">
                    <div id="day_wrapper1" class="digitbox">0</div>
                    <div id="day_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="hour_wrapper1" class="digitbox">0</div>
                    <div id="hour_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="minute_wrapper1" class="digitbox">0</div>
                    <div id="minute_wrapper2" class="digitbox">0</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="second_wrapper1" class="digitbox">0</div>
                    <div id="second_wrapper2" class="digitbox">0</div>
                    <br style="clear:both"/>
                    <div id="days" class="smallbox">days</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="hours" class="smallbox">hours</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="minutes" class="smallbox">mins</div>
                    <div class="digitbox">&nbsp;</div>
                    <div id="seconds" class="smallbox">secs</div>
                    <br style="clear:both"/>
                    to the Year of the Monkey
                </div>
            </div>


This is the CSS. There's a whole chunk of it for drawing the different facial features of the monkey and I'm not going to explore that here. Grab the code from this link.
            #cny_overlay
            {
                top:0px;
                left:0px;
                width:100%;
                height:100%;
                position:fixed;
                background-color:rgba(200,200,200,0.2);
            }

            #cny_container
            {
                width:80%;
                height:80%;
                top:10%;
                left:10%;
                border-radius:20px;
                position:absolute;
                background-color:rgba(200,200,200,1);
            }

            #year_wrapper
            {
                width:800px;
                height:200px;
                margin-top:10%;
                margin-left: auto;
                margin-right: auto;
                position:relative;
                overflow:visible;
            }

            .yeardigit_wrapper
            {
                width:200px;
                height:200px;
                float:left;
                text-align: center;
                font-size:180px;
                font-weight:bold;
                font-family:verdana;
            }

            #monkey_wrapper
            {
                width:200px;
                height:200px;
                background-color:#000000;
                border-radius:50%;
                float:left;
            }

            #message_wrapper
            {
                width:800px;
                height:100px;
                margin-top:20px;
                margin-left: auto;
                margin-right: auto;
                position:relative;
                text-align:center;
                font-size:30px;
                font-weight:bold;
                font-family:verdana;
                color:rgba(254,254,0,0);
                -webkit-transition: all 1s;
                transition: all 1s;
            }

            #time_wrapper
            {
                width:330px;
                margin:5% auto 0 auto;
                text-align:center;
                font-family:verdana;
                font-weight:bold;
                font-size:30px;
                color:rgba(0,0,0,1);
                -webkit-transition: all 1.5s;
                -webkit-transform:perspective(500px) rotateX(0deg);
                -webkit-transform-origin:50% 50%;
                -webkit-perspective-origin:50% 100%;
                transition: all 1.5s;
                transform:perspective(500px) rotateX(0deg);
                transform-origin:50% 50%;
                perspective-origin:50% 100%;            }

            .digitbox
            {
                width:30px;
                height:60px;
                font-size:40px;
                float:left;
                text-align:center;
            }

            .smallbox
            {
                width:60px;
                height:60px;
                font-size:15px;
                text-align:center;
                float:left;
            }

            .
            .
            .
            Click here for the rest
            .
            .
            .


This is what you should have. The timer digits out of the box? Not to worry, this is just to show you what the monkey should look like when it's displayed. But in practice, the monkey and the timer will not be shown on-screen at the same time.


Make the monkey and message disappear with this. We'll make it appear again with the start_animation() function.
                <div id="year_wrapper" style="display:none;">
                    <div class="yeardigit_wrapper">2</div>
                    <div id="monkey_wrapper">
                        <div class="monkey monkey_face" style="width:90px;height:90px;margin-left:20px;margin-top:30px;"></div>
                        <div class="monkey monkey_face" style="width:90px;height:90px;margin-left:90px;margin-top:30px;"></div>
                        <div class="monkey monkey_face" style="width:140px;height:140px;margin-left:30px;margin-top:50px;"></div>
                        <div id="monkey_brow1" class="monkey"></div>
                        <div id="monkey_brow2" class="monkey"></div>
                        <div id="monkey_eye1" class="monkey"></div>
                        <div id="monkey_eye2" class="monkey"></div>
                        <div id="monkey_nostril1" class="monkey"></div>
                        <div id="monkey_nostril2" class="monkey"></div>
                        <div id="monkey_lip" class="monkey"></div>   
                    </div>
                    <div class="yeardigit_wrapper">1</div>
                    <div class="yeardigit_wrapper">6</div>
                </div>


This is what you should have now. Notice now that the year_wrapper div is hidden, it no longer takes up space on screen. The message_wrapper div, however, is merely transparent and still occupies space. Therefore the timer digits have shifted lower.


Now for the start_animation() function...
            function start_animation()
            {
                clearInterval(countdowntimer);

                document.getElementById("time_wrapper").style.transform="perspective(500px) rotateX(360deg)";
                document.getElementById("time_wrapper").style.webkitTransform="perspective(500px) rotateX(360deg)";
                document.getElementById("time_wrapper").style.color="rgba(0,0,0,0)";

                setTimeout(function(){document.getElementById("time_wrapper").style.display="none";},1500);
                setTimeout(function(){document.getElementById("year_wrapper").style.display="block";},1500);
                setTimeout(function(){document.getElementById("message_wrapper").style.color="rgba(254,100,0,1)";},1600);
            }


The year_wrapper div appears just as the timer_wrapper div disappears completely, and then the message_wrapper div that holds your greeting message appears too. Cool, right? But that's not all.
            function start_animation()
            {
                clearInterval(countdowntimer);

                document.getElementById("time_wrapper").style.transform="perspective(500px) rotateX(360deg)";
                document.getElementById("time_wrapper").style.webkitTransform="perspective(500px) rotateX(360deg)";
                document.getElementById("time_wrapper").style.color="rgba(0,0,0,0)";

                setTimeout(function(){document.getElementById("time_wrapper").style.display="none";},1500);
                setTimeout(function(){document.getElementById("year_wrapper").style.display="block";},1500);
                setTimeout(function(){tremble(20,0);},1550);
                setTimeout(function(){document.getElementById("message_wrapper").style.color="rgba(254,100,0,1)";},1600);
            }

            function tremble(varvariance,varvalue)
            {
                if (varvalue<varvariance)
                {
                    trembletimer=setTimeout(function(){tremblingdigits(varvariance,varvalue);},50);
                }
            }

            function tremblingdigits(varvariance,varvalue)
            {

            }


Tremblingdigits? What's that?

Just another nifty special effect! After year_wrapper appears, the tremble() function is called, using the trembletimer variable as a timer, with two parameters. varvariance is the number of times that  trembling digits() is eventually called, and also the maximum variance. varvalue is used to offset varvariance. Sound confusing? It'll be clear soon.

OK, the objective here is to make the "2016" and the monkey head tremble when they appear. That'll be some impact! Of course, at the end of the sequence, the trembling gets less and less pronounced till the "2016" and the monkey head come to a complete halt.
            function tremblingdigits(varvariance,varvalue)
            {
                clearTimeout(trembletimer);

                var digits=document.getElementsByClassName("yeardigit_wrapper");
                var monkey=document.getElementById("monkey_wrapper");

                for (var i=0;i<digits.length;i++)
                {
                    digits[i].style.marginTop=(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"px";
                    digits[i].style.transform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";    
                    digits[i].style.webkitTransform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";   
                }

                monkey.style.marginTop=(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"px";
                monkey.style.transform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";
                monkey.style.webkitTransform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";
               
                trembletimer=setTimeout(function(){tremblingdigits(varvariance,varvalue+1);},50);
            }

            function generaterandomno(varmin,varmax)
            {
                return Math.floor((Math.random() * (varmax-varmin+1)) + varmin);
            }


So here, trembletimer is first cleared. The digits and the monkey head are then rotated by varvariance number of degrees and varvariance number of pixels. varvariance is further modified during this time with a generaterandomno() function, with the maximum value being (varvariance-varvalue) and the minimum value being 0. And of course, generaterandomno() is called again to determine if the displacement/rotation is positive or negative. So you'll see the digits and the monkey head trembling in all directions.

At the end of the tremblingdigits() function, tremblingdigits() is called again (again, using the trembletimer variable as a timer), this time with an increase in varvalue. So varvalue gets progressively larger, and the value of (varvariance-varvalue) gets progressively smaller, which is what we're going for.

Modify your code again. This ensures that the trembling stops when varvalue gets to 20. If it gets to the point where varvalue is equal to varvariance, the animation stops.
            function tremblingdigits(varvariance,varvalue)
            {
                clearTimeout(trembletimer);

                if (varvalue<varvariance)
                {
                    var digits=document.getElementsByClassName("yeardigit_wrapper");
                    var monkey=document.getElementById("monkey_wrapper");

                    for (var i=0;i<digits.length;i++)
                    {
                        digits[i].style.marginTop=(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"px";
                        digits[i].style.transform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";   
                    }

                    monkey.style.marginTop=(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"px";
                    monkey.style.transform="rotate("+(generaterandomno(0,varvariance-varvalue)*(generaterandomno(0,1)==0?-1:1))+"deg)";
               
                    trembletimer=setTimeout(function(){tremblingdigits(varvariance,varvalue+1);},50);
                }
            }


Add this one last line of code, and you're done! This ensures that your timer can be clicked away if it starts being a nuisance on your site.
<div id="cny_overlay" onclick="this.style.display='none';">

Enough monkey business! Have a happy a fruitful Lunar New Year!
T___T

No comments:

Post a Comment