设计思路: 先匀速转动三圈,之后在礼物前五个开始减速,最后停在礼物上即选中预设的礼物。如此循环,直至抽中三个礼物。
先将前端设计好:
<div id="luckyActivity">
<div id="choujiang">
<div id="luck">
<div class="luckList1">
<div class="luckItem"><a class="i1" data-intro="礼物1"></a></div>
<div class="luckItem"><a class="i2" data-intro="礼物2"></a></div>
<div class="luckItem"><a class="i3" data-intro="礼物3"></a></div>
<div class="luckItem"><a class="i4" data-intro="礼物4"></a></div>
</div>
<div class="luckList2">
<div class="luckGroup">
<div class="luckItem"><a class="i12" data-intro="礼物12"></a></div>
<div class="luckItem"><a class="i11" data-intro="礼物11"></a></div>
</div>
<div id="luckBtn">
<a id="iwanna">我要抽奖</a>
<p class="luckInfo">随机抽取3样奖品</p>
</div>
<div class="luckGroup">
<div class="luckItem"><a class="i5" data-intro="礼物5"></a></div>
<div class="luckItem"><a class="i6" data-intro="礼物6"></a></div>
</div>
</div>
<div class="luckList3">
<div class="luckItem"><a class="i10" data-intro="礼物10"></a></div>
<div class="luckItem"><a class="i9" data-intro="礼物9"></a></div>
<div class="luckItem"><a class="i8" data-intro="礼物8"></a></div>
<div class="luckItem"><a class="i7" data-intro="礼物7"></a></div>
</div>
</div>
</div>
这里要注意的是礼物的顺序以及编号,左上角为1号礼物,以此顺时针推算,最后一个礼物为12号。
data-intro用来为礼物的描述做铺垫,我们可以为每一个礼物添加hover效果:
代码如下:
$('.luckItem a').hover(function() {
$(this).addClass('prizeIntro');
}, function() {
$(this).removeClass('prizeIntro');
})
.prizeIntro:after {
content: attr(data-intro);
display: block;
position: absolute;
top: 48px;
height: 29px;
width: 75px;
font-size: 14px;
color: #fff;
line-height: 29px;
text-align: center;
background-color: rgba(0, 0, 0, 0.7);
}
其次,就是轮转的核心部分了。
var prizeIndex = 1; // 礼物序号
var liwu = [7, 5, 11]; // 后端值(将要选取的三个礼物)
var l = 0; // liwu[l]
var distance = 5; //距离多少格前开始减速
function roundPrize() {
//此方法的作用是使我们的选中框先匀速转三圈
return new Promise(function(resolve) {
var timeStep = 45; // 转动速度(毫秒)
var round = 0; // 用于记录转了多少下
setTimeout(function(){
$('.luckItem a').removeClass('onPrize');
$('.i'+ prizeIndex++ ).addClass('onPrize');
if(prizeIndex > 12) { //转12次一循环
prizeIndex = 1;
}
//算法中最复杂的往往是数学部分
//转动次数是确定于一个值的,譬如我们要选取的第一个礼物是5号,那么我们应该转动36次(在被选取礼物前五格开始减速)
//其次我们在实际测试中会发现,如果后一个礼物值小于前一个(liwu[l] - liwu[l-1] < 0)的情况下,选中框只转两圈就开始减速了,因此我们需要做一个判断,在 小于0 的情况下加上12(即加一圈)
if( round++ < ( ( liwu[l] - (liwu[l-1] || 0) ) > 0 ? 36 : 48 )
+ liwu[l] - (distance + 1) - ( (liwu[l-1]) || 0 ) ) {
setTimeout(arguments.callee, timeStep);
} else {
resolve();
}
},timeStep)
})
}
至此,我们完成了匀速转动的效果,接着就是减速的部分:
$('#iwanna').click(function() {
$('.i'+ prizeIndex).addClass('onPrize');
$('.luckInfo').hide();
$('#iwanna').text('抽奖中...');
var call = arguments.callee;
roundPrize().then(function() {
let timeStep = 200; // 初速度
var ratio = 1.5; // 速率变化系数
var endline = Math.floor( timeStep * Math.pow(ratio, distance-1) );
setTimeout(function() {
$('.luckItem a').removeClass('onPrize');
$('.i'+ prizeIndex++ ).addClass('onPrize');
//'.onPrize'即滚动中的选中效果
if(prizeIndex > 12) {
prizeIndex = 1;
}
if(timeStep < endline) {
timeStep *= ratio;
setTimeout(arguments.callee, timeStep);
} else {
$('.onPrize').parent().addClass('prizeMe').end().removeClass('onPrize');
//'.prizeMe'即礼物选中的CSS样式
l++; // 下一份礼物
if(l < 3) { //循环三次即选三次礼物
setTimeout(call, 1000)
} else {
$('.luckItem a').removeClass('onPrize');
//此处可以添加结束事件
}
}
}, timeStep)
})
})
在部分老版本编辑环境中 ES6 语法可能会报错,但这并不影响在浏览器中的运行。