Friday 28 January 2022

Web Tutorial: The Lucky Number Generator, redux (Part 2/2)

Time to draw a tiger!

We begin this process by changing the code here to reflect the year. This is 2022, which means a tiger will be drawn.

tt_cny2022.html
<body onload="cny(2022)">


In the JavaScript file, we create an If block for the tiger in the createAnimal() function.

cny.js
if (animalName == "tiger")
{

}


Start off with the face. It's a variable named - you guesse it - face. It's a div that is 80 by 70 pixels, round corners and an orange background. We make sure it floats right because we want it flush to the right of the screen. This div has no border except for the bottom, which is a 5 pixel thick white line. Since we have rounded corners, the effect is going to be nice, like a beard. Lastly, we make sure the cursor property is set to pointer.

cny.js
if (animalName == "tiger")
{
    var face = document.createElement("div");
    face.style.width = "80px";
    face.style.height = "70px";
    face.style.borderRadius = "50%";
    face.style.position = "relative";
    face.style.backgroundColor = "rgba(255, 100, 0, 1)";
    face.style.borderBottom = "5px solid rgba(255, 255, 255, 1)";
    face.style.float = "right";
    face.style.cursor = "pointer";

}


Return face, and that's it for now.

cny.js
if (animalName == "tiger")
{
    var face = document.createElement("div");
    face.style.width = "80px";
    face.style.height = "70px";
    face.style.borderRadius = "50%";
    face.style.position = "relative";
    face.style.backgroundColor = "rgba(255, 100, 0, 1)";
    face.style.borderBottom = "5px solid rgba(255, 255, 255, 1)";
    face.style.float = "right";
    face.style.cursor = "pointer";

    return face;
}


You see what we're doing here?


This tiger needs some ears. We are going to have a container div for these, in a variable called ears. We make it fit 100% of its parent, which will be face. The height will be 35 pixels. At the end, before returning face, we append ears to face.

cny.js
    face.style.cursor = "pointer";

    var ears = document.createElement("div");
    ears.style.width = "100%";
    ears.style.height = "35px";
    ears.style.position = "relative";

    face.appendChild(ears);


    return face;
}


Now we declare leftEar and rightEar. They're both oval orange divs, except that one is floated left, and one right. Both are appended into ears.

cny.js
    face.style.cursor = "pointer";

    var ears = document.createElement("div");
    ears.style.width = "100%";
    ears.style.height = "35px";
    ears.style.position = "relative";

    var leftEar = document.createElement("div");
    leftEar.style.width = "15px";
    leftEar.style.height = "35px";
    leftEar.style.float = "left";
    leftEar.style.backgroundColor = "rgba(255, 100, 0, 1)";
    leftEar.style.borderRadius = "50%";

    var rightEar = document.createElement("div");
    rightEar.style.width = "15px";
    rightEar.style.height = "35px";
    rightEar.style.float = "right";
    rightEar.style.backgroundColor = "rgba(255, 100, 0, 1)";
    rightEar.style.borderRadius = "50%";

    ears.appendChild(leftEar);    
    ears.appendChild(rightEar);


    face.appendChild(ears);
    
    return face;
}


Those are some adorable ears!


This tiger needs stripes. For this, we are going to do pretty much what we did for the ears - create a container div and fill it with content, except we'll have two divs. These divs are stripes and stripes2.

cny.js
    ears.appendChild(leftEar);    
    ears.appendChild(rightEar);

    var stripes = document.createElement("div");

    var stripes2 = document.createElement("div");


    face.appendChild(ears);
    
    return face;
}    


The height and width of stripes will fill the entirety of its parent, which will be face. It is round, floated left, and the color property has been set to black. More importantly, we set the overflow property to hidden because the text that we're putting into, three pipe symbols, may get out of the div. For this, the position property will also be set to relative. Text and font properties and the top margin are really up to you, but I would stick with what I've done here because it's all been verified through trial and error.

cny.js
    ears.appendChild(leftEar);    
    ears.appendChild(rightEar);

    var stripes = document.createElement("div");
    stripes.style.width = "100%";
    stripes.style.height = "100%";
    stripes.style.borderRadius = "50%";
    stripes.style.position = "relative";
    stripes.style.color = "rgba(0, 0, 0, 1)";
    stripes.style.float = "left";
    stripes.style.overflow = "hidden";
    stripes.style.marginTop = "-35px";
    stripes.style.fontSize = "2em";
    stripes.style.fontWeight = "bold";
    stripes.style.lineHeight = "0.5em";
    stripes.style.textAlign = "center";
    stripes.innerHTML = "|||";


    var stripes2 = document.createElement("div");

    face.appendChild(ears);
    
    return face;
}    


Append stripes to face.

cny.js
    var stripes = document.createElement("div");
    stripes.style.width = "100%";
    stripes.style.height = "100%";
    stripes.style.borderRadius = "50%";
    stripes.style.position = "relative";
    stripes.style.color = "rgba(0, 0, 0, 1)";
    stripes.style.float = "left";
    stripes.style.overflow = "hidden";
    stripes.style.marginTop = "-35px";
    stripes.style.fontSize = "2em";
    stripes.style.fontWeight = "bold";
    stripes.style.lineHeight = "0.5em";
    stripes.style.textAlign = "center";
    stripes.innerHTML = "|||";

    var stripes2 = document.createElement("div");

    face.appendChild(ears);
    face.appendChild(stripes);
    
    return face;
}


Nice, right?! There's more...


This is pretty much more of the same for stripes2, but we use a series of equal signs as text content.

cny.js
    stripes.style.textAlign = "center";
    stripes.innerHTML = "|||";

    var stripes2 = document.createElement("div");
    stripes2.style.width = "100%";
    stripes2.style.height = "100%";
    stripes2.style.borderRadius = "50%";
    stripes2.style.position = "relative";
    stripes2.style.color = "rgba(0, 0, 0, 1)";
    stripes2.style.float = "left";
    stripes2.style.overflow = "hidden";
    stripes2.style.marginTop = "-70px";
    stripes2.style.fontSize = "2em";
    stripes2.style.fontWeight = "bold";
    stripes2.style.lineHeight = "0.5em";
    stripes2.style.textAlign = "center";
    stripes2.innerHTML = "<br /><br />===<br />===";


    face.appendChild(ears);
    face.appendChild(stripes);
    face.appendChild(stripes2);
    
    return face;
}


Horizontal stripes!


Now for the eyes! This will be a container div, called eyes. In this, we will have divs, leftEye and rightEye. They're basically elliptical divs with a little bit of rotation thrown in.

cny.js
    stripes2.style.textAlign = "center";
    stripes2.innerHTML = "<br /><br />===<br />===";

    var eyes = document.createElement("div");
    eyes.style.width = "80px";
    eyes.style.height = "20px";
    eyes.style.float = "left";
    eyes.style.margin = "-45px auto 0 auto";
    eyes.style.fontSize = "15px";
    eyes.style.fontWeight = "bold";
    eyes.style.color = "rgba(0, 0, 0, 1)";

    var leftEye = document.createElement("div");
    leftEye.style.width = "20px";
    leftEye.style.height = "5px";
    leftEye.style.float = "left";
    leftEye.style.border = "3px solid rgba(0, 0, 0, 1)";
    leftEye.style.borderRadius = "50%";
    leftEye.style.backgroundColor = "rgba(255, 100, 0, 1)";
    leftEye.style.transform = "rotate(20deg)";
    leftEye.style.marginLeft = "10px";

    var rightEye = document.createElement("div");
    rightEye.style.width = "20px";
    rightEye.style.height = "5px";
    rightEye.style.float = "right";
    rightEye.style.border = "3px solid rgba(0, 0, 0, 1)";
    rightEye.style.borderRadius = "50%";
    rightEye.style.backgroundColor = "rgba(255, 100, 0, 1)";
    rightEye.style.transform = "rotate(-20deg)";
    rightEye.style.marginRight = "10px";

    eyes.appendChild(leftEye);    
    eyes.appendChild(rightEye);    


    face.appendChild(ears);
    face.appendChild(stripes);
    face.appendChild(stripes2);
    face.appendChild(eyes);

    return face;
}    


Those are some big eyes.


Next up is the snout. It's a circular orange area that will block off some of the stripes. Within it, there will be a black letter "Y" to represent the nose.

cny.js
    eyes.appendChild(leftEye);    
    eyes.appendChild(rightEye);    

    var snout = document.createElement("div");
    snout.style.width = "50px";
    snout.style.height = "40px";
    snout.style.borderRadius = "50%";
    snout.style.position = "relative";
    snout.style.float = "left";
    snout.style.margin = "-35px 0 0 15px";
    snout.style.fontSize = "15px";
    snout.style.textAlign = "center";
    snout.style.fontWeight = "bold";
    snout.style.backgroundColor = "rgba(255, 100, 0, 1)";
    snout.style.borderBottom = "5px solid rgba(255, 255, 255, 1)";
    snout.style.color = "rgba(0, 0, 0, 1)";    
    snout.innerHTML = "Y";


    face.appendChild(ears);
    face.appendChild(stripes);
    face.appendChild(stripes2);
    face.appendChild(eyes);
    face.appendChild(snout);

    return face;
}        


Definitely taking shape now.


Finally, we give the tiger a mouth. It will be superimposed on top of snout by way of the margin property. Here, I have made it a white div with black text. The "teeth" are actually a series of "V"s. Note that the letter spacing and line height are specified so as to pack them close together and make them look like a row of teeth. Also, the transition property is specified and we give it a class name of cny_mouth because we will be animating this.

cny.js
    snout.style.color = "rgba(0, 0, 0, 1)";    
    snout.innerHTML = "Y";

    var mouth = document.createElement("div");
    mouth.className = "cny_mouth";
    mouth.style.width = "40px";
    mouth.style.height = "10px";
    mouth.style.borderRadius = "5px";
    mouth.style.position = "relative";
    mouth.style.float = "left";
    mouth.style.overflow = "hidden";
    mouth.style.margin = "-20px 0 0 20px";
    mouth.style.fontSize = "15px";
    mouth.style.textAlign = "center";
    mouth.style.backgroundColor = "rgba(255, 255, 255, 1)";
    mouth.style.color = "rgba(0, 0, 0, 1)";    
    mouth.style.lineHeight = "0.7em";
    mouth.style.letterSpacing = "-0.05em";
    mouth.style.transition = "all 0.1s";
    mouth.innerHTML = "VVVVV";


    face.appendChild(ears);
    face.appendChild(stripes);
    face.appendChild(stripes2);
    face.appendChild(eyes);
    face.appendChild(snout);
    face.appendChild(mouth);

    return face;
}


This is what those teeth look like!


Now we will animate this. Go to the cny() function and add an If block after the one for the pig.

cny.js
if (animalNames[yearIndex] == "pig")
{
    setInterval
    (
        function()
        {
            var eyes = document.getElementsByClassName("cny_eyes");

            eyes[0].innerHTML = "-&nbsp;&nbsp;-";

            setTimeout
            (
                function()
                {
                    eyes[0].innerHTML = "&bull;&nbsp;&nbsp;&bull;";
                },
                500
            );
        },
        5000
    );

    setInterval
    (
        function()
        {
            var tail = document.getElementsByClassName("cny_tail");

            tail[0].style.transform = "rotate(-185deg)";

            setTimeout
            (
                function()
                {
                    tail[0].style.transform = "rotate(-175deg)";
                },
                500
            );
        },
        1000
    );        
}

if (animalNames[yearIndex] == "tiger")
{
        
}


In here, we use the setInterval() function with a 1 second interval. And inside the callback, we use a setTimeout() function with a half-second duration.

cny.js
if (animalNames[yearIndex] == "tiger")
{
    setInterval
    (
        function()
        {
            setTimeout
            (
                function()
                {

                },
                500
            );
        },
        1000
    );     
   
}


Then we declare mouth inside the first callback, setting it to the array returned by getting all elements with the class cny_mouth. The first (and only) element of mouth will have height set to 5 pixels. The callback within the setTimeout() function will set it back to 10 pixels. Note that since we had the div's overflow property set to hidden, there should be no issue with the teeth jutting out of the resized mouth.

cny.js
if (animalNames[yearIndex] == "tiger")
{
    setInterval
    (
        function()
        {
            var mouth = document.getElementsByClassName("cny_mouth");
            mouth[0].style.height = "5px";


            setTimeout
            (
                function()
                {
                    mouth[0].style.height = "10px";
                },
                500
            );
        },
        1000
    );        
}


If you refresh, the tiger should be snarling!


And clicking on the tiger still works!


The Year of the Tiger approaches!

Be bold and ferocious like the tiger, and may you achieve your goals in 2022!

It's been a pleasure presenting this web tutorial. Do enjoy your Lunar New Year.


Here's to a hu-mongous year!
T___T

No comments:

Post a Comment