Tuesday, 22 March 2016

Web Tutorial: The Easter Egg Generator (Part 3/4)

Bands, dots and stars - what could make your Easter egg even more awesome? What's the spirit of Easter? Why, hope and renewal of course. And for that, we need to add a rainbow to your egg.

If you've gone through the web tutorial for the CSS Rainbowlizer, this is pretty similar. One div with seven other divs nested within it. Here's what we add to the egg_wrapper div.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="band1" class="band"></div>
                <div id="band2" class="band"></div>
                <div id="band3" class="band"></div>

                <div id="polkadot1" class="polkadot"></div>
                <div id="polkadot2" class="polkadot"></div>
                <div id="polkadot3" class="polkadot"></div>
                <div id="polkadot4" class="polkadot"></div>
                <div id="polkadot5" class="polkadot"></div>

                <div id="star_wrapper1" class="star_wrapper">
                    <div id="star1_part1" class="star_part1"></div>
                    <div id="star1_part2" class="star_part2"></div>
                    <div id="star1_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper2" class="star_wrapper">
                    <div id="star2_part1" class="star_part1"></div>
                    <div id="star2_part2" class="star_part2"></div>
                    <div id="star2_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper3" class="star_wrapper">
                    <div id="star3_part1" class="star_part1"></div>
                    <div id="star3_part2" class="star_part2"></div>
                    <div id="star3_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper4" class="star_wrapper">
                    <div id="star4_part1" class="star_part1"></div>
                    <div id="star4_part2" class="star_part2"></div>
                    <div id="star4_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper5" class="star_wrapper">
                    <div id="star5_part1" class="star_part1"></div>
                    <div id="star5_part2" class="star_part2"></div>
                    <div id="star5_part3" class="star_part3"></div>
                </div>

                <div id="rainbow_wrapper">
                    <div id="rainbowband1" class="rainbowband"></div>
                    <div id="rainbowband2" class="rainbowband"></div>
                    <div id="rainbowband3" class="rainbowband"></div>
                    <div id="rainbowband4" class="rainbowband"></div>
                    <div id="rainbowband5" class="rainbowband"></div>
                    <div id="rainbowband6" class="rainbowband"></div>
                    <div id="rainbowband7" class="rainbowband"></div>   
                </div>
            </div>
        </div>


Here are the CSS styles for the rainbow. The rainbow_wrapper div is rotated around its middle and positioned over the egg much the same was as the bands. Each div inside the rainbow_wrapper div is styled by rainbowband. The position property is absolute because they all overlap each other, and the border-radius property is set to 50% because they are all ellipses. However, they will appear only as curved bands because the rest of it is truncated by the rainbow_wrapper div's overflow property, which is set to hidden.

And of course, each individual band's background is transparent and its border set to 10 pixels, each of a different color.
            .star_part1
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(0deg);
                 transform:rotate(0deg);
            }

            .star_part2
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(70deg);
                 transform:rotate(70deg);
            }

            .star_part3
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(-70deg);
                 transform:rotate(-70deg);
            }

            #rainbowband1{background:transparent;border:10px solid #FF0000;}
            #rainbowband2{background:transparent;border:10px solid #FF9900;}
            #rainbowband3{background:transparent;border:10px solid #FFFF00;}
            #rainbowband4{background:transparent;border:10px solid #00FF00;}
            #rainbowband5{background:transparent;border:10px solid #0000FF;}
            #rainbowband6{background:transparent;border:10px solid #440044;}
            #rainbowband7{background:transparent;border:10px solid #FF00FF;}
           
            #rainbow_wrapper
            {
                width:1000px;
                height:100px;
                -webkit-transform-origin:50% 50%;

                transform-origin:50% 50%;
                overflow:hidden;
                position:absolute;
            }

            .rainbowband
            {
                border-radius:50%;
                position:absolute;
            }


You should be seeing this now. The rainbow appears as just a pink dot because we haven't positioned the individual bands properly. This will be fixed via JavaScript.


Hide the rainbow by adding this line.
            #rainbow_wrapper
            {
                width:1000px;
                height:100px;
                -webkit-transform-origin:50% 50%;
                transform-origin:50% 50%;
                overflow:hidden;
                display:none;
                position:absolute;
            }


Then add this code to your dashboard_wrapper div. As with all the others, it's a set of controls to manipulate your rainbow. The functions are pretty much the same as those used for bands. There's a hidden field, hid_thickness_rainbow, which stores the thickness of the rainbow bands.
             <fieldset>
                <legend>Star Settings <input type="checkbox" id="cb_pnlStars" onclick="setvisible('pnlStars');"></legend>
                <div id="pnlStars">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper1" onclick="setvisible('star_wrapper1');"><br />
                                <div class="verticaltext">Star 1</div>
                            </td>
                            <td><label for="col_star1">Color</label></td>
                            <td><input type="color" id="col_star1" value="#05F044" onchange="setstar('star1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star1">Size</label></td>
                            <td><input type="range" id="rng_size_star1" class="smallslider" value="20" min="20" max="100" step="20" onchange="setstchaar('star1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper1" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper1">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper1" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper1">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper1" class="smallslider" value="150" min="0" max="200" step="10" onchange="sety('star_wrapper1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper1">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper1" class="smallslider" value="160" min="20" max="500" step="10" onchange="setz('star_wrapper1');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper2" onclick="setvisible('star_wrapper2');"><br />
                                <div class="verticaltext">Star 2</div>
                            </td>
                            <td><label for="col_star2">Color</label></td>
                            <td><input type="color" id="col_star2" value="#EE0088" onchange="setstar('star2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star2">Size</label></td>
                            <td><input type="range" id="rng_size_star2" class="smallslider" value="40" min="20" max="100" step="20" onchange="setstar('star2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper2">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper2" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper2">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper2" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper2">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper2" class="smallslider" value="250" min="0" max="200" step="10" onchange="sety('star_wrapper2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper2">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper2" class="smallslider" value="170" min="20" max="500" step="10" onchange="setz('star_wrapper2');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper3" onclick="setvisible('star_wrapper3');"><br />
                                <div class="verticaltext">Star 3</div>
                            </td>
                            <td><label for="col_star3">Color</label></td>
                            <td><input type="color" id="col_star3" value="#FF9966" onchange="setstar('star3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star3">Size</label></td>
                            <td><input type="range" id="rng_size_star3" class="smallslider" value="20" min="20" max="100" step="20" onchange="setstar('star3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper3">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper3" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper3">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper3" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('star_wrapper3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper3">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper3" class="smallslider" value="280" min="0" max="200" step="10" onchange="sety('star_wrapper3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper3">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper3" class="smallslider" value="180" min="20" max="500" step="10" onchange="setz('star_wrapper3');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper4" onclick="setvisible('star_wrapper4');"><br />
                                <div class="verticaltext">Star 4</div>
                            </td>
                            <td><label for="col_star4">Color</label></td>
                            <td><input type="color" id="col_star4" value="#0055FF" onchange="setstar('star4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star4">Size</label></td>
                            <td><input type="range" id="rng_size_star4" class="smallslider" value="80" min="20" max="100" step="20" onchange="setstar('star4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper4">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper4" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper4">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper4" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper4">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper4" class="smallslider" value="50" min="0" max="200" step="10" onchange="sety('star_wrapper4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper4">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper4" class="smallslider" value="190" min="20" max="500" step="10" onchange="setz('star_wrapper4');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper5" onclick="setvisible('star_wrapper5');"><br />
                                <div class="verticaltext">Star 5</div>
                            </td>
                            <td><label for="col_star5">Color</label></td>
                            <td><input type="color" id="col_star5" value="#040444" onchange="setstar('star5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star5">Size</label></td>
                            <td><input type="range" id="rng_size_star5" class="smallslider" value="20" min="40" max="100" step="20" onchange="setstar('star5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper5">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper5" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper5">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper5" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('star_wrapper5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper5">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper5" class="smallslider" value="100" min="0" max="200" step="10" onchange="sety('star_wrapper5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper5">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper5" class="smallslider" value="200" min="20" max="500" step="10" onchange="setz('star_wrapper5');"></td>
                        </tr>               
                    </table>
                </div>
            </fieldset>   

            <fieldset>
                <legend>Rainbow Settings <input type="checkbox" id="cb_pnlRainbow" onclick="setvisible('pnlRainbow');"></legend>
                <div id="pnlRainbow">
                    <table>
                        <tr>
                            <td rowspan="2">
                                <input type="checkbox" id="cb_rainbow_wrapper" onclick="setvisible('rainbow_wrapper');"><br />
                                <div class="verticaltext">Rainbow</div>
                            </td>
                            <td><label for="rng_height_rainbow_wrapper">Height</label><input type="hidden" id="hid_thickness_rainbow" value="10"></td>
                            <td><input type="range" id="rng_height_rainbow_wrapper" class="smallslider" value="100" min="20" max="500" step="20" onchange="setheight('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_rainbow_wrapper">Width</label></td>
                            <td><input type="range" id="rng_width_rainbow_wrapper" class="smallslider" value="500" min="500" max="1500" step="10" onchange="setwidth('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_rainbow_wrapper">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_rainbow_wrapper" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('rainbow_wrapper');"></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_rainbow_wrapper">Y</label></td>
                            <td><input type="range" id="rng_y_rainbow_wrapper" class="smallslider" value="60" min="0" max="500" step="10" onchange="sety('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_rainbow_wrapper">Z</label></td>
                            <td><input type="range" id="rng_z_rainbow_wrapper" class="smallslider" value="150" min="20" max="500" step="10" onchange="setz('rainbow_wrapper');"></td>
                        </tr>           
                    </table>
                </div>
            </fieldset>


Now, modify your JavaScript. The setwidth() function requires some tweaking for the rainbow. When the rainbow_wrapper div's width is changed, its margin-left property needs to be adjusted relative to the width of the egg, so it will always be in the middle of the egg.
            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    var marginleft=($("#egg_wrapper").width()-$("#egg").width())/2;
                    $("#egg").css("margin-left", marginleft+"px");
                }

                if (varid=="rainbow_wrapper")
                {
                    $("#rainbow_wrapper").css("margin-left","-"+(($("#rainbow_wrapper").width()-$("#egg").width())/2)+"px");
                }
            }


Also, each rainbow band's width is adjusted at the same time to cater for the thickness of the rainbow band. Remember each rainbow band is an ellipse? Therefore if the border thickness adds to its width, we have to offset this twice - one time for each side that will be affected.
            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    var marginleft=($("#egg_wrapper").width()-$("#egg").width())/2;
                    $("#egg").css("margin-left", marginleft+"px");
                }

                if (varid=="rainbow_wrapper")
                {
                    $("#rainbow_wrapper").css("margin-left","-"+(($("#rainbow_wrapper").width()-$("#egg").width())/2)+"px");
                    $(".rainbowband").width($("#rng_width_"+varid).val()-($("#hid_thickness_rainbow").val()*2));
                }
            }


Next, we modify the setheight() function to cater for the rainbow_wrapper div. Changing the height will affect the height of each rainbow band, which is set at twice the height of the rainbow_wrapper div.
            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;
                    $("#egg").css("margin-top", margintop+"px");
                }

                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                }
            }


The thickness is also affected - and it's set at 1/20th of the rainbow_wrapper div's height.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).css("border-width", $("#hid_thickness_rainbow").val()+"px");
                    });
                }


And after that, each rainbow band's margin-top property needs to be set so that they align on top of each other neatly, taking the border thickness of each rainbow band into account.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).get(0).style.borderWidth=$("#hid_thickness_rainbow").val()+"px";
                    });
                   
                    $("#rainbowband1").css("margin-top", "0px";
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                }


And of course, since all this has been changed, we'll need to run the setwidth() function to properly align the entire rainbow_wrapper div.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).get(0).style.borderWidth=$("#hid_thickness_rainbow").val()+"px";
                    });
                   
                    $("#rainbowband1").css("margin-top", "0px";
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                    setwidth("rainbow_wrapper");
                }


Finally, the setvisible() function needs to be tweaked.
            function setvisible(varid)
            {
                if ($("#cb_"+varid).prop("checked"))
                {
                    $("#"+varid).show();

                    if (varid.indexOf("band")==0)
                    {
                        setcolor(varid);
                        setheight(varid);
                        setrotation(varid);
                        sety(varid);
                        setz(varid);
                    }

                    if (varid.indexOf("polkadot")==0)
                    {
                        setcolor(varid);
                        setheight(varid);
                        setwidth(varid);
                        setx(varid);
                        sety(varid);
                        setz(varid);
                    }

                    if (varid.indexOf("star")==0)
                    {
                        setstar(varid.replace("_wrapper",""));
                        setx(varid);
                        sety(varid);
                        setz(varid);
                    }

                    if (varid=="rainbow_wrapper")
                    {
                        setheight("rainbow_wrapper");
                        setrotation("rainbow_wrapper");
                        sety("rainbow_wrapper");
                        setz("rainbow_wrapper");
                    }
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


Modify as shown to hide the controls initially.
            #pnlBands,#pnlPolkadots,#pnlStars,#pnlRainbow{display:none;}


Let's take a look at what we have so far. Try the controls. Do they work?


Well, we've added bands, dots, stars and a rainbow. Give yourself a pat on the back; that was an insane amount of work on a text editor! If you set the overflow property of the egg div to hidden, you should see the full effects now.
            #egg
            {
                width:250px;
                height:350px;
                border:1px solid #888888;
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 overflow:hidden;
                 position:absolute;
                 z-index:10;
            }


Now when you add the bands, polkadots, stars and rainbow, they no longer stick out of the egg! You'll also see that when you start expanding all the panels in the dashboard div, the screen expands but the egg stays in one place. That's because of the position propety of the egg_wrapper div, which was set to fixed.



Next

Some final touches, a fix or two. Watch this space!

No comments:

Post a Comment