jQuery Wheel of Fortune Demo

Sam Deering

Just a quick demo of a the Wheel of Fortune. Random spin animating wheel of fortune with win/lose realize.

Note: For better testing of the demo below open it in jsfiddle.

Requirements:

Demo Code

The Code – jQuery

window.WHEELOFFORTUNE = {

    cache: {},

    init: function () {
        console.log('controller init...');

        var _this = this;
        this.cache.wheel = $('.wheel');
        this.cache.wheelMarker = $('.marker');
        this.cache.wheelSpinBtn = $('.wheel'); //im using the wheel as the spin button but simply change this to a button if you want.

        //mapping is backwards as wheel spins clockwise //1=win
        this.cache.wheelMapping = [400, 120, 80, 750, 150, 300, 60, 175, 500, 125, 75, 1000, 120, 200, 90, 600, 100, 250].reverse();

        this.cache.wheelSpinBtn.on('click', function (e) {
            e.preventDefault();
            if (!$(this).hasClass('disabled')) _this.spin();
        });

        //reset wheel
        this.resetSpin();

        //setup prize events
        this.prizeEvents();
    },

    spin: function () {
        console.log('spinning wheel');

        var _this = this;

        // reset wheel
        this.resetSpin();

        //disable spin button while in progress
        this.cache.wheelSpinBtn.addClass('disabled');

        /*
            Wheel has 10 sections.
            Each section is 360/10 = 36deg.
        */
        var deg = 1500 + Math.round(Math.random() * 1500),
            duration = 6000; //optimal 6 secs

        _this.cache.wheelPos = deg;

        //transition queuing
        //ff bug with easeOutBack
        this.cache.wheel.transition({
            rotate: '0deg'
        }, 0)
            .transition({
            rotate: deg + 'deg'
        }, duration, 'easeOutCubic');

        //move marker
        _this.cache.wheelMarker.transition({
            rotate: '-20deg'
        }, 0, 'snap');

        //just before wheel finish
        setTimeout(function () {
            //reset marker
            _this.cache.wheelMarker.transition({
                rotate: '0deg'
            }, 300, 'easeOutQuad');
        }, duration - 500);

        //wheel finish
        setTimeout(function () {
            // did it win??!?!?!
            var spin = _this.cache.wheelPos,
                degrees = spin % 360,
                percent = (degrees / 360) * 100,
                segment = Math.ceil((percent / 6)),  //divided by number of segments
                win = _this.cache.wheelMapping[segment - 1]; //zero based array

            console.log('spin = ' + spin);
            console.log('degrees = ' + degrees);
            console.log('percent = ' + percent);
            console.log('segment = ' + segment);
            console.log('win = ' + win);

            //display dialog with slight delay to realise win or not.
            setTimeout(function () {
                alert('you won '+win+'!');
            }, 700);

            //re-enable wheel spin
            _this.cache.wheelSpinBtn.removeClass('disabled');

        }, duration);

    },

    resetSpin: function () {
        this.cache.wheel.transition({
            rotate: '0deg'
        }, 0);
        this.cache.wheelPos = 0;
    }

}

window.WHEELOFFORTUNE.init();

The Code – CSS

.wheel-wrap {
    position: relative;
    width: 550px;
    height: 550px;
    overflow: hidden;
    margin: 0 auto;
    z-index: 1;
}
.marker {
    top: 10px;
    left: 250px;
    z-index: 2;
    position: absolute;
}
.wheel {
    top: 90px;
    left: 75px;
    width: 550px;
    z-index: 1;
}

The Code – HTML

<div class="wheel-wrap">
    <img class="wheel" src="http://jquery4u.com/images/wheeloffortune.png" />
    <img class="marker" src="http://jquery4u.com/images/marker.png" />
</div>

wheeloffortune

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • blogakyol

    It’s nice post and idea, but need to fix bug which is seem on the picture. I just tried it 3-4 times and it alerts wrong number, maybe it’s about the cache don’t know exactly but you can take a look at it if you have free time, just wanted to show that, keep nice post going on ! :)

    • Dave Mound

      Yep got the same issue. Has anyone found a fix for this yet?

    • http://jquery4u.com/ jQuery4u
      • blogakyol

        yeap, it works fine on jsfiddle, Thanks !

    • smate1990

      easy… rotates 20 degrees. but 19 numbers on the wheel.

      • smate1990

        or… i just can’t count :$ :D

  • Ivan

    Hello, realy nice tutorial. Tell me you have 18 (rows) how i can set only 8 (rows, segment) ? Thanks

    • http://jquery4u.com/ jQuery4u

      with 8 segments, 360/16 = 22.5% per segment.

      so this part is now:

      //move marker
      _this.cache.wheelMarker.transition({
      rotate: ‘-22.5deg’
      }, 0, ‘snap’);

      - also you need to change the wheelMapping in cache.
      - also change this line: segment = Math.ceil((percent / 6)), //divided by number of segments
      - also change the image used to 16 segments

      That’s basically it.

      • Olivier

        Hello Thank you for this nice tutorial.

        I have tried with 12 segments/portions in the wheel
        > 360/12 = 30

        what i done :

        1/ //move marker
        _this.cache.wheelMarker.transition({
        rotate: ‘-30deg’
        }, 0, ‘snap’);

        2/ also change the wheelMapping in cache:
        this.cache.wheelMapping = ['r1','r2','b1','b2','o1','o2','v1','v2','j1','j2','g1','g2'].reverse();

        3/ change this line: segment = Math.ceil((percent / 12)), //divided by number of segments

        4/ also change the image used to 16 segments (cf attachment)

        but there is something wrong.

        can you help me ?

        • http://jquery4u.com/ jQuery4u

          Hi mate, can you put your code in a jsfiddle.net?

  • Ben Dubuisson

    It doesn’t work on the jsfiddle either

  • ควย

    ควย กูอุตสาห์พยายาม เสือกหมุนเบี้ยว ไอสาสสสสสสสสสสสสสสสสสสสสสสส

  • Achyut Jhunjhunwala

    Hi Admin,

    Really a nice post. But can you help me with a small change. Currently you are having a button, on click of which the wheel rotates randomly and a number popus out. My requirement is user should be able to spin the wheel with mouse drag instead of clicking the button. Please suggest

    • http://jquery4u.com/ jQuery4u

      Hi Achyut, I would probably suggest using something like hammer.js to capture the drag motion and start the spinning action. Obviously you can make it more complex by having different spinning directions and different spinning speeds based on drag amount.

  • scott-BHG

    where is the value 6 coming from for the divider?

  • polikin

    I see the bug on JsFiddle

    • polikin

      win = 100, not 120.

  • Rupak

    Hello,

    Can you please provide update on the issue where it alerts wrong number. The problem is showing in the demo as well in jsfiddle.

    A quick response would be appreciated.

  • http://google.com araffles

    Hi Sam, great post! I have to make a spinning wheel and you saved me a TON of time. Just curious, the wheel doesn’t spin in IE 9 or 8 so I was thinking of doing a browser detect and playing an animated gif in case, but I can’t figure out what to be detecting exactly. Some IE9 browsers spin the wheel, others just show the “Win” message without any animating. Hopefully you can help out. Thanks!

    • http://google.com araffles

      Just checked out Modernizr and a few other sites which say they can get rotation transition working in IE 6+ but it is way too advanced for me. Anyone know a good reference point for getting this fantastic spinning wheel to load in IE 6+?

      • http://jquery4u.com/ jQuery4u

        Why oh why do you need it to work in IE6+. Surely IE8 is the BARE minimum you need?

        • http://google.com araffles

          Truly IE8 is the lowest I need it to work with, but I figure whatever works on IE8 will most likely work on IE6, but I’ll be very happy with it working on IE8. Any tips? I’ve been banging my head on this for days now. Thanks.