JSFiddle - React, Tailwind, and code Playground
HTML
<div class="wheel">
<div class="wheel-wrapper">
<div class="wheel-item wheel-black">
<p>17</p>
</div>
<div class="wheel-item wheel-red">
<p>18</p>
</div>
<div class="wheel-item wheel-black">
<p>19</p>
</div>
<div class="wheel-item wheel-red">
<p>20</p>
</div>
<div class="wheel-item wheel-green">
<p>0</p>
</div>
<div class="wheel-item wheel-black">
<p>1</p>
</div>
<div class="wheel-item wheel-red">
<p>2</p>
</div>
<div class="wheel-item wheel-black">
<p>3</p>
</div>
<div class="wheel-item wheel-red">
<p>4</p>
</div>
<div class="wheel-item wheel-black">
<p>5</p>
</div>
<div class="wheel-item wheel-red">
<p>6</p>
</div>
<div class="wheel-item wheel-black">
<p>7</p>
</div>
<div class="wheel-item wheel-red">
<p>8</p>
</div>
<div class="wheel-item wheel-black">
<p>9</p>
</div>
<div class="wheel-item wheel-red">
<p>10</p>
</div>
<div class="wheel-item wheel-black">
<p>11</p>
</div>
<div class="wheel-item wheel-red">
<p>12</p>
</div>
<div class="wheel-item wheel-black">
<p>13</p>
</div>
<div class="wheel-item wheel-red">
<p>14</p>
</div>
<div class="wheel-item wheel-black">
<p>15</p>
</div>
<div class="wheel-item wheel-red">
<p>16</p>
</div>
<div class="wheel-item wheel-black">
<p>17</p>
</div>
<div class="wheel-item wheel-red">
<p>18</p>
</div>
<div class="wheel-item wheel-black">
<p>19</p>
</div>
<div class="wheel-item wheel-red">
<p>20</p>
</div>
<div class="wheel-item wheel-green">
<p>0</p>
</div>
<div class="wheel-item wheel-black">
<p>1</p>
</div>
<div class="wheel-item wheel-red">
<p>2</p>
</div>
<div class="wheel-item wheel-black">
...
SCSS
.wheel {
width: 470px;
height: 50px;
padding: 10px 9px;
margin: 0 auto;
overflow: hidden;
&-wrapper {
width: 1950px;
}
&-item {
float: left;
width: 50px;
height: 30px;
color: white;
text-align: center;
p {
line-height: 30px;
margin: 0;
}
}
&-green {
background: #62c30c;
}
&-black {
background: #3a3a3a;
}
&-red {
background: #e63359;
}
&-pointer {
width: 0;
height: 50px;
position: absolute;
top: 10px;
left: 0;
right: 0;
margin: auto;
border-left: 2px solid orange;
}
}
JavaScript
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element) {
window.setTimeout(callback, 1000 / 60);
};
})();
// t: current time
// b: start value
// c: change in value
// d: duration
function easeOutSine(t, b, c, d) {
return c * Math.sin(t/d * (Math.PI/2)) + b;
}
SpinWheel = function(id) {
var _this = this;
_this.el = $('.wheel-wrapper');
_this.position = 0;
_this.items = 20;
_this.itemsWidth = 50;
_this.spinTime = 6000;
_this.running = false;
_this.resultId = id;
_this.totalWidth = (_this.items + 1) * _this.itemsWidth;
_this.start = function() {
var resultOffset = _this.resultId * _this.itemsWidth;
var loops = 3; //+ Math.floor(Math.random() * 3);
_this.totalDistance = (loops * _this.totalWidth) + resultOffset;
_this.running = true;
_this.startTime = performance.now();
(function gameLoop(rafTime) {
_this.update(rafTime);
if (_this.running) {
requestAnimFrame(gameLoop);
}
})(_this.startTime);
};
_this.update = function(rafTime) {
var deltaTime = rafTime - _this.startTime;
if (deltaTime >= _this.spinTime) {
_this.running = false;
return;
}
// t = timeFraction
var t = easeOutSine(deltaTime, 0, 1, _this.spinTime);
_this.position = Math.round(t * _this.totalDistance);
var translateX = _this.position % _this.totalWidth;
console.log('translateX:', translateX, 'position:', _this.position, 'deltaTime:', deltaTime);
_this.el.css({
'transform': 'translateX(-' + translateX + 'px)'
});
};
_this.init = function() {
_this.start()
};
_this.init();
return _this;
};
//will be passed in: 20 = number of items
var resultId = parseInt(Math.random() * 20);
var wheel = new SpinWheel(resultId);