现在不少app都会有一些抽奖活动,热门的抽奖当属九宫格循环抽奖,而还有一种抽奖形式也是比较常见,比如老虎机的形式
那么我们就用JQ和CSS实现一下这个效果。
其实这个效果和实现一个轮播图是有异曲同工之妙的
假设现在有1,2,3三个奖品,我们可以在一个ul内使用多个序列拼接成一个长列表:1–2--3–1--2–3--1–2--3–1--2–3…以此类推
每一组1–2--3视为一个集合,抽奖开始从第一个集合的某个奖品开始,到最后一个集合的某个奖品结束,中间使用transition加transform实现动效。
当每一次抽奖动效完成后ul会挺在最后一个集合的元素上,这个时候就需要让ul‘瞬移’一下,移动到当前这个奖项对应的第一个集合中的奖项,以便下一次抽奖
有了这个大概的思路,就可以着手于实现了
我们实现的是上文提到的那个例子,但是为了简洁,我们的dom结构就先定义简单一点
<div class="game-content">
<div class="game-goods-wrap">
<div class="game-goods-list">
<div class="game-goods" style="background: #ffffff;">
<div class="game-goods-box" id="game1">
<ul class="game-goods-ul">ul>
div>
div>
<div class="game-goods" style="background: #ffffff;">
<div class="game-goods-box" id="game2">
<ul class="game-goods-ul">ul>
div>
div>
<div class="game-goods" style="background: #ffffff;">
<div class="game-goods-box" id="game3">
<ul class="game-goods-ul">ul>
div>
div>
div>
div>
<span class="game-btn">span>
div>
然后我们开始书写核心动效实现的封装函数,对外提供可以配置的接口option:
luckGame: function(options) {
var defaults = {
'gameLen': '10', // 奖品的数量
'game_pagesize': 6,//生成多少圈同样的东西,调节速度用
'zj_arr': { //中奖数组,第一个表示是否中奖,第二个中奖号码
'is_win':1,
'number':8
}
};
var settings = Object.assgin(defaults, options);
w_config={
'w':$(window).width(),
'h':$(window).height()
}
var gameArr=[]; // 奖品滚动的列表
var gameLen=settings.gameLen; // 奖品的种类数量
var game_list_h=''; // 奖品滚动列表的高度
var game_init=[]; // 页面载入时随机的选择状态
var game_list_item_h=0; // 单个奖品元素的高度
//每次进来随机3个数字,来启动当前的选择的状态
for (var i = 0; i < 3; i++) {
game_init.push(Math.floor(Math.random() * gameLen));
}
createGame();
$(window).resize(function(){
createGame();
})
// 初始化游戏
function createGame(){
getHeight();
setLi();
pushLi(gameArr);
start();
}
function getHeight(){
w_config={
'w':$(window).width(),
'h':$(window).height()
}
// 由于抽奖机本身的大小根据屏幕大小自适应,所以奖品高度需要计算
// 实际场景下一般都是定高的
game_list_item_h=(w_config.w*320/750*0.5*0.7).toFixed(2);
}
//设置奖品
function setLi(){
// 拼接实际的滚动数组
for (var j = 1; j <= settings.game_pagesize; j++) {
for (var i = 1; i <= gameLen; i++) {
gameArr.push({'type':j,'index':i,'src':'images/'+i+'.png'});
}
}
}
//写入,初始化奖品的滚动
function pushLi(arr){
var html_str='';
// 根据滚动数组生成li
for (var i = 0; i < arr.length; i++) {
html_str+='+ game_list_item_h+'px" data-index="' + arr[i]['index']+'" data-type="'+arr[i]['type']+'">+ arr[i]['src']+'">';
}
$(".game-goods-ul").each(function(e){
$(this).empty().append(html_str);
game_list_h=$(this).height();
console.log('game_list_item_h',game_init);
y=game_list_item_h*game_init[e];
$(this).css({
'transition-duration': '0ms',
'transform':'translate(0px, -'+y+'px) translateZ(0px)'
})
});
}
// 开始抽奖
function start(){
// 这一块是点击开始动效
// 但实际场景中一般是点击之后和后台进行交互
// 获取到中奖信息之后再开始动效
$(".game-btn").click(function(){
//如果中奖
if(settings.zj_arr.is_win==1)
{
$(".game-goods-ul").each(function(e){
setTimeout(function(){
y=(settings.zj_arr.number+settings.gameLen*(settings.game_pagesize-1))*game_list_item_h;
$(".game-goods-ul").eq(e).css({
'transition-duration': '5000ms',
'transform':'translate(0px, -'+y+'px) translateZ(0px)'
})
}, e*300);
// 判断最后面是否完毕
// 抽奖动画完成后回到type=1的地方,等待下一次抽奖
$("#game3").find(".game-goods-ul").on("webkitTransitionEnd", function() {
y=settings.zj_arr.number*game_list_item_h;
$(".game-goods-ul").css({
'transition-duration': '0ms',
'transform':'translate(0px, -'+y+'px) translateZ(0px)'
})
$("#game3").find(".game-goods-ul").unbind("webkitTransitionEnd");
})
})
}else
{
// 不中奖的时候哦生成随记停留的奖项,但是确保不能三个奖项一样
numrand=randNum2();
console.log(numrand);
// 不中奖的时候
$(".game-goods-ul").each(function(e){
y2=(numrand[0])*game_list_item_h;
y3=(numrand[1])*game_list_item_h;
y4=(numrand[2])*game_list_item_h;
setTimeout(function(){
y=(numrand[e]+settings.gameLen*(settings.game_pagesize-1))*game_list_item_h;
$(".game-goods-ul").eq(e).css({
'transition-duration': '5000ms',
'transform':'translate(0px, -'+y+'px) translateZ(0px)'
})
}, e*300);
//判断最后面是否完毕
// 抽奖动画完成后回到type=1的地方,等待下一次抽奖
$("#game3").find(".game-goods-ul").on("webkitTransitionEnd", function() {
$(".game-goods-ul").eq(2).css({
'transition-duration': '00ms',
'transform':'translate(0px, -'+y4+'px) translateZ(0px)'
})
$("#game3").find(".game-goods-ul").unbind("webkitTransitionEnd");
})
$("#game2").find(".game-goods-ul").on("webkitTransitionEnd", function() {
$(".game-goods-ul").eq(1).css({
'transition-duration': '00ms',
'transform':'translate(0px, -'+y3+'px) translateZ(0px)'
})
$("#game2").find(".game-goods-ul").unbind("webkitTransitionEnd");
})
$("#game1").find(".game-goods-ul").on("webkitTransitionEnd", function() {
$(".game-goods-ul").eq(0).css({
'transition-duration': '00ms',
'transform':'translate(0px, -'+y2+'px) translateZ(0px)'
})
$("#game1").find(".game-goods-ul").unbind("webkitTransitionEnd");
})
})
}
})
}
// 生成不中奖时候的随机显示序列
function randNum2(){
a=Math.floor(Math.random() * gameLen);
b=Math.floor(Math.random() * gameLen);
c=Math.floor(Math.random() * gameLen);
arr=[];
if(a==b)
{
return randNum2();
}else
{
return arr=[a,b,c];
}
}
}
然后我们就可以像这样传入配置,这一块实际场景中是点击按钮过后再传入配置,当配置传入之后调用函数,直接开始动画:
luckGame({
'zj_arr': {
'is_win':1,
'number':9//从0算起,就是10了
},
gameLen:10,//产品抽奖数量,
game_pagesize:6
});
以上就是核心的动效实现,如果是使用vue或者react之类的框架,那么我们则只需要关注数据本身就行,由数据去驱动视图,省去了繁杂的DOM操作,整个过程会更加简洁。