Saturday 15 August 2015

Web Tutorial: Wheel of Fortune (Part 1/4)

Are ya feeling lucky?!

Let's do something fun today. Let's make a Wheel of Fortune using HTML, CSS and JavaScript. It'll be able to spin when the mouse cursor is dragged over it, and when it stops, the prize won will be displayed!

For starters, we'll need a wheel. (well, duh!) And the obvious question here is...

How does one make a multi-segmented wheel in CSS?

I'm going to dedicate the first part of this web tutorial, to showing you just how you pull off this nifty little trick.

Starting HTML:
<!DOCTYPE html>
<html>
    <head>
        <title>Wheel</title>
    </head>

    <body>
        <div id="wheel_wrapper">

        </div>
    </body>
</html>


The wheel_wrapper div is meant to hold all the separate parts of the wheel together. Because in the later parts of the tutorial, this div is what we're going to spin.

Next, we're going to style wheel_wrapper, like so. I've made it 500 by 500 pixels, and centered it in the middle of the screen by setting the margin property to 0 auto 0 auto. That's shorthand for: no margin for top and bottom, auto for left and right.
<!DOCTYPE html>
<html>
    <head>
        <title>Wheel</title>

        <style type="text/css">
            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }
        </style>

    </head>

    <body>
        <div id="wheel_wrapper">

        </div>
    </body>
</html>


Now, I want you to do yourself a favor and add this to your CSS. This line basically ensures that all divs will have a nice red outline so you can easily visualize what we're trying to accomplish here.

        <style type="text/css">
            div {border:1px solid #ff0000;}

            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }
        </style>


See what I mean? Things could get a little complicated from here on, and I don't want you to get confused. We can delete that line later. But, for now, you have a visual aid.


OK, now. Basic question. What is a circle made of? Two semi-circles, of course! So we're going to create the first semicircle, like so.
<!DOCTYPE html>
<html>
    <head>
        <title>Wheel</title>

        <style type="text/css">
            div {border:1px solid #ff0000;}

            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }

            .semicircle1
            {
                margin-left:-250px;
            }

            .segment_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
            }

        </style>
    </head>

    <body>
        <div id="wheel_wrapper">
            <div class="segment_wrapper semicircle1">

            </div>
        </div>
    </body>
</html>


You'll notice that this particular div has two CSS classes attached to it. While the semicircle1 class is particular to this div, the segment_wrapper class will be recycled for the other semicircle we'll create later on.

So let's take a look at what these classes accomplish.

segment_wrapper is so named because this div is meant to encapsulate all the different segments of the semicircle. These segments will be dealt with soon. It has the full size of the wheel_wrapper div (500 by 500 pixels).

semicircle1 has the margin-left property set to -250 pixels, which means only the right half of the div is inside the wheel_wrapper div.



Next, we'll be placing segments of the semicircle inside that div.Let's begin with the first segment.

    <body>
        <div id="wheel_wrapper">
            <div class="segment_wrapper semicircle1">
                    <div class="segment1 segment">
                        <p>A</p>
                    </div>

            </div>
        </div>
    </body>
</html>


Again, two CSS classes are attached to it - segment1, and segment. segment is meant to be reused for other segment divs, while segment1 is particular to this one only.

The CSS classes defined as follows:
        <style type="text/css">
            div {border:1px solid #ff0000;}

            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }

            .semicircle1
            {
                margin-left:-250px;
            }

            .segment_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
            }

            .segment
            {
                width:250px;
                height:250px;
                position:absolute;
                margin-left:250px;
                margin-top:0px;
                transform-origin:0% 100%;
                -webkit-transform-origin:0% 100%;
            }

            .segment1
            {
                background-color:#44FF55;
                z-index:10;
                transform: rotate(0deg);
                -webkit-transform: rotate(0deg);
            }

        </style>


Notice that segment's width and height properties are half of the parent div, i.e. 250 pixels? That's not a coincidence. transform-origin is set to the bottom right of the div. This is common for all segments. Now this is the first segment (thus the class segment1),and it will be starting at 0 degrees. I've set the background-color property to a random color, in this case, a nice aqua. z-index is at 10. Take note, this will be relevant soon.

See how it looks now!


Now add the other 6 segments in the semicircle.
    <body>
        <div id="wheel_wrapper">
            <div class="segment_wrapper semicircle1">
                    <div class="segment1 segment">
                        <p>A</p>
                    </div>
                    <div class="segment2 segment">
                        <p>B</p>
                    </div>
                    <div class="segment3 segment">
                        <p>C</p>
                    </div>
                    <div class="segment4 segment">
                        <p>D</p>
                    </div>
                    <div class="segment5 segment">
                        <p>E</p>
                    </div>
                    <div class="segment6 segment">
                        <p>F</p>
                    </div>
            </div>
        </div>
    </body>
</html>


And add in the classes segment2 to segment6. For each of these, different random colors have been assigned as background colors. The z-index property increases by 10 for each one, because they are all going to overlap, with the largest numbered segment being at the top.

Also, they have all been rotated a certain number of degrees. Some simple math here: How many degrees are there in a semicircle? 180. So for 6 segments, each one would be rotated by an additional 30 degrees.
        <style type="text/css">
            div {border:1px solid #ff0000;}

            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }

            .semicircle1
            {
                margin-left:-250px;
            }

            .segment_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
            }

            .segment
            {
                width:250px;
                height:250px;
                position:absolute;
                margin-left:250px;
                margin-top:0px;
                transform-origin:0% 100%;
                -webkit-transform-origin:0% 100%;
            }

            .segment1
            {
                background-color:#44FF55;
                z-index:10;
                transform: rotate(0deg);
            }

            .segment2
            {
                background-color:#990033;
                z-index:20;
                transform: rotate(30deg);
                -webkit-transform: rotate(30deg);
            }

            .segment3
            {
                background-color:#AA00AA;
                z-index:30;
                transform: rotate(60deg);
                -webkit-transform: rotate(60deg);
            }

            .segment4
            {
                background-color:#44FFAA;
                z-index:40;
                transform: rotate(90deg);
                -webkit-transform: rotate(90deg);
            }

            .segment5
            {
                background-color:#FF9900;
                z-index:50;
                transform: rotate(120deg);
                -webkit-transform: rotate(120deg);
            }

            .segment6
            {
                background-color:#2299FF;
                z-index:60;
                transform: rotate(150deg);
                -webkit-transform: rotate(150deg);
            }
        </style>


This is how it should look now.


Doesn't look much like a semicircle, does it? We're going to rectify that. Make the following changes to your segment_wrapper class.

            .segment_wrapper
            {
                width:500px;
                height:500px;
                border-radius:50%;
                overflow:hidden;

                position:relative;
            }

border-radius:50% makes the corners of your div perfectly round, making it a circle. overflow:hidden ensures that all the corners of the segments that stick outside of the div, are hidden!

Getting into shape now...


Now what we need to do is trim off the part of the semicircle that sticks out. Enclose your div in an outer div, like so.
    <body>

        <div id="wheel_wrapper">
            <div class="semicircle_wrapper wheel1">
                <div class="segment_wrapper semicircle1">
                    <div class="segment1 segment">
                        <p>A</p>
                    </div>
                    <div class="segment2 segment">
                        <p>B</p>
                    </div>
                    <div class="segment3 segment">
                        <p>C</p>
                    </div>
                    <div class="segment4 segment">
                        <p>D</p>
                    </div>
                    <div class="segment5 segment">
                        <p>E</p>
                    </div>
                    <div class="segment6 segment">
                        <p>F</p>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>


And again, it'll have two CSS classes attached to it - semicircle_wrapper and wheel1. Add those classes below.
        <style type="text/css">
            div {border:1px solid #ff0000;}

            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }

            .semicircle_wrapper
            {
                width:250px;
                height:500px;
                overflow:hidden;
                position:relative;
            }

            .wheel1
            {
                float:right;
            }


            .semicircle1
            {
                margin-left:-250px;
            }

            .segment_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
            }

            .segment
            {
                width:250px;
                height:250px;
                position:absolute;
                margin-left:250px;
                margin-top:0px;
                transform-origin:0% 100%;
                -webkit-transform-origin:0% 100%;
            }

            .segment1
            {
                background-color:#44FF55;
                z-index:10;
                transform: rotate(0deg);
                -webkit-transform: rotate(0deg);
            }

            .segment2
            {
                background-color:#990033;
                z-index:20;
                transform: rotate(30deg);
                -webkit-transform: rotate(30deg);
            }

            .segment3
            {
                background-color:#AA00AA;
                z-index:30;
                transform: rotate(60deg);
                -webkit-transform: rotate(60deg);
            }

            .segment4
            {
                background-color:#44FFAA;
                z-index:40;
                transform: rotate(90deg);
                -webkit-transform: rotate(90deg);
            }

            .segment5
            {
                background-color:#FF9900;
                z-index:50;
                transform: rotate(120deg);
                -webkit-transform: rotate(120deg);
            }

            .segment6
            {
                background-color:#2299FF;
                z-index:60;
                transform: rotate(150deg);
                -webkit-transform: rotate(150deg);
            }
        </style>


semicircle_wrapper will be reused for the other semicircle. And wheel1 is just for this particular div.

semicircle_wrapper has the full height of the wheel, but only half the width. Just like, well, a semicircle. Again, the overflow property has been set to hidden, to trim off the fat.

wheel1 sets the div to float to the right side of the containing div, like so.


Now, remove the first line of your CSS that says div {border:1px solid #ff0000;}, and you have a beautifully colored semicircle!


Ain't she a beauty? So all we have to do now, is create another semicircle with segments, and this one will be the other half of the wheel. I'll put in the code for you, and the CSS.
<!DOCTYPE html>
<html>
    <head>
        <title>Wheel</title>

        <style type="text/css">
            #wheel_wrapper
            {
                width:500px;
                height:500px;
                position:relative;
                margin:0 auto 0 auto;
            }

            .semicircle_wrapper
            {
                width:250px;
                height:500px;
                overflow:hidden;
                position:relative;
            }

            .wheel1
            {
                float:right;
            }

            .wheel2
            {
                float:left;
            }


            .semicircle1
            {
                margin-left:-250px;
            }

            .semicircle2
            {
                margin-left:0px;
            }


            .segment_wrapper
            {
                width:500px;
                height:500px;
                border-radius:50%;
                overflow:hidden;
                position:relative;
            }

            .segment
            {
                width:250px;
                height:250px;
                position:absolute;
                margin-left:250px;
                margin-top:0px;
                transform-origin:0% 100%;
                -webkit-transform-origin:0% 100%;
            }

            .segment1
            {
                background-color:#44FF55;
                z-index:10;
                transform: rotate(0deg);
                -webkit-transform: rotate(0deg);
            }

            .segment2
            {
                background-color:#990033;
                z-index:20;
                transform: rotate(30deg);
                -webkit-transform: rotate(30deg);
            }

            .segment3
            {
                background-color:#AA00AA;
                z-index:30;
                transform: rotate(60deg);
                -webkit-transform: rotate(60deg);
            }

            .segment4
            {
                background-color:#44FFAA;
                z-index:40;
                transform: rotate(90deg);
                -webkit-transform: rotate(90deg);
            }

            .segment5
            {
                background-color:#FF9900;
                z-index:50;
                transform: rotate(120deg);
                -webkit-transform: rotate(120deg);
            }

            .segment6
            {
                background-color:#2299FF;
                z-index:60;
                transform: rotate(150deg);
                -webkit-transform: rotate(150deg);
            }

            .segment7
            {
                background-color:#FF2255;
                z-index:10;
                transform: rotate(180deg);


            }

            .segment8
            {
                background-color:#AAFF22;
                z-index:20;
                    transform: rotate(210deg);
            }

            .segment9
            {
                background-color:#9944EE;
                z-index:30;
                    transform: rotate(240deg);
            }

            .segment10
            {
                background-color:#FF3300;
                z-index:40;
                transform: rotate(270deg);
                -webkit-transform: rotate(270deg);
            }

            .segment11
            {
                background-color:#338800;
                z-index:50;
                transform: rotate(300deg);

                -webkit-transform: rotate(300deg); 
            }

            .segment12
            {
                background-color:#EE33AA;
                z-index:60;
                transform: rotate(330deg);

                -webkit-transform: rotate(330deg);
             }
        </style>
    </head>

    <body>
        <div id="wheel_wrapper">
            <div class="semicircle_wrapper wheel2">
                <div class="segment_wrapper semicircle2">
                    <div class="segment7 segment">
                        <p>G</p>
                    </div>
                    <div class="segment8 segment">
                        <p>H</p>
                    </div>
                    <div class="segment9 segment">
                        <p>I</p>
                    </div>
                    <div class="segment10 segment">
                        <p>J</p>
                    </div>
                    <div class="segment11 segment">
                        <p>K</p>
                    </div>
                    <div class="segment12 segment">
                        <p>L</p>
                    </div>
                </div>
            </div>


            <div class="semicircle_wrapper wheel1">
                <div class="segment_wrapper semicircle1">
                    <div class="segment1 segment">
                        <p>A</p>
                    </div>
                    <div class="segment2 segment">
                        <p>B</p>
                    </div>
                    <div class="segment3 segment">
                        <p>C</p>
                    </div>
                    <div class="segment4 segment">
                        <p>D</p>
                    </div>
                    <div class="segment5 segment">
                        <p>E</p>
                    </div>
                    <div class="segment6 segment">
                        <p>F</p>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>


And this is how it should look now.


Great work! We now have a full wheel of 12 different colored segments, labelled A to L.

Next

We'll need to control this little beauty's spinning. I'll show you the JavaScript codes it takes to set this thing in motion.



No comments:

Post a Comment