JSFiddle - React, Tailwind, and code Playground
by Gwyn Milcote
HTML
<span id='games_wheel_prize'>Click the pointy thing and see which segment you land on.</span>
<br>
You've made <span id='games_wheel_spun'>0</span> spins so far.
<br><span id='games_wheel_status'></span>
<div id='games_wheel_container'>
<div id='games_wheel'></div>
<button id='games_wheel_spinner'>
<span>Spin!</span>
<div id='pointer'></div>
</button>
</div>
CSS
#games_wheel_container {
position: relative;
width: 500px;
height: 500px;
margin: 20px auto;
border: 1px solid white;
padding: 10px;
text-align: center;
}
/*
* This div contains the wheel image, and gets rotated.
* Use border-radius: 100% to turn square div round,
* and 'trim' anything outside the circle image.
* You can see the background-color as a 'border'.
*/
#games_wheel {
position: absolute;
top: 50%;
left: 50%;
margin-top: -250px;
margin-left: -250px;
width: 500px;
height: 500px;
background-color: green;
background-image: url('http://griffusion.elementfx.com/pics/ui/wheel.gif');
border-radius: 100%;
}
/*
* This is the middle bit that user clicks on.
*/
#games_wheel_spinner {
cursor: pointer;
color: white;
font-weight: bold;
border: none;
position: absolute;
width: 50px;
height: 50px;
top: 235px;
left: 235px;
border-radius: 100%;
z-index: 2;
background-color: blue;
}
/*
* The little arrow pointing upwards. Optional.
*/
#games_wheel_spinner #pointer {
position: absolute;
width: 0;
height: 0;
top: -8px;
left: 15px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid blue;
}
JavaScript
(function($) {
$.fn.fortune = function(args){
if(args === undefined){
throw(new Error("You must define the options.prizes"));
}
var options = $.extend({}, {
prices: args,
duration: 2500,
separation: 2,
min_spins: 5,
max_spins: 15,
onSpinBounce: function() {}
}, args);
var fortune = this;
var prices_amount = Array.isArray(options.prices)?options.prices.length:options.prices;
var prices_delta = 360 / prices_amount;
var is_spinning = false;
fortune.spin = function(price) {
price = typeof price === "number"?price:Math.floor(Math.random() * prices_amount);
var deferred = $.Deferred();
var position = Math.floor(prices_delta * (price - 1/2) + randomBetween(options.separation, prices_delta - options.separation));
var spins = randomBetween(options.min_spins, options.max_spins);
var final_position = 360 * spins + position;
var prev_position = 0;
var is_bouncing = false;
is_spinning = true;
fortune
.css({
"transform": "rotate(" + final_position + "deg)",
"-webkit-transform": "rotate(" + final_position + "deg)",
"transition": "transform " + options.duration + "ms cubic-bezier(.17,.67,.12,.99)",
"-webkit-transition": "-webkit-transform " + options.duration + "ms cubic-bezier(.17,.67,.12,.99)"
})
.siblings('.spin').removeClass('bounce');
var bounceSpin = function() {
var curPosition = Math.floor(getRotationDegrees(fortune)),
mod = Math.floor((curPosition + prices_delta*0.5) % prices_delta),
diff_position,
position_threshold = prices_delta/5,
distance_threshold = prices_delta/10;
prev_position = Math.floor(curPosition < prev_position ? prev_position - 360 : prev_position);
diff_position = curPosition - prev_position;
if ((mod < position_threshold && diff_position < distance_threshold) ||
(mod <...