最终效果实例下载:http://www.oschina.net/code/snippet_2352644_54997
一.大转盘准备工作
网上的一个抽奖大转盘实例http://www.jq22.com/yanshi2252
这就是我们要开发的效果,不过我们是让指针转,我们先分析这个效果:
结构有2部分,上面是指针背景图,下面是奖项图
点击指针元素开始抽奖,会转动一定圈数停下来
停下来的位置指针指使那个奖项,就会弹出获奖信息提示
这是参考效果,我们分析自己的大概实现:
同样上下2部分
点击指针转动,不过是指针动
转动一定圈数停止
根据指向弹出获奖信息
设置抽奖次数,假如只能三次
设置不同奖项中奖概率
在最后我们在写一个九宫格大转盘
二.如何转起来
转就是css3的2d旋转处理,css3就不写了,看下面。
三.静态结构搭建
问题出现了,那就是两张图,一个奖项图,一个指针图,不能设计不可怕,我们直接把参考效果的扒取下来就好了,省略下载操作,我们已经有图了,请下载。
back.png
pointer.png
书写我们的静态结构,背景图目录看css设置:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;} #zhizhen{animation:animations 2s linear infinite forwards;transform:rotate(0deg);} @keyframes animations{ 0%{transform:rotate(0deg);} 100%{transform:rotate(360deg);} } </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 }; </script> </html>
一个基于css3动画配合2d变化的旋转指针就出现了,下面我们将分析top ,left,旋转圆心为何如此设置的。
四.静态结构重要样式分析
红线的就是最核心样式,首先是top和left的设置:
这不需要太多解释吧,篮框就是我们指针,我们摆正后测量就可以了,
注意:一定要1px无偏差摆正,不然旋转时就跑偏了!
我们把指针已经放在中心位置,因为图不是正方形,需要具体测量,可见把指针处理为正方形会大大简化我们的处理。
这就是旋转圆心位置,指针是非正方形,我们的测量位置就是在中心圆中心,不过y要加上偏差。
什么是旋转圆心?我们在桌子上摆好一个日记本,然后按住一个点,日记本转动,按住的点就是圆心。
为了测试是否可以不跑偏的转动,我们结合动画进行测试。
五.利用js开始转起来
我们利用动画已经不停的转了起来,利用js我们如何转动?
一说到js,还说到动,我们要瞬间想到setInterval函数,我们利用间隔函数,动态的不断修改2d变化旋转的角度大小,就可以转起来了,我们同样加入事件的处理,点击后触发转动:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //监听点击事件 zhizhen.onclick=function(){ dbox=setInterval(dong,dtime); }; function dong(){ deg+=cc; zhizhen.style.transform="rotate(" + deg + "deg)"; } }; </script> </html>
六.转动一定角度后停止
我们知道,转一定圈数后,是要停止的,停止的位置根据指向,会弹出中奖信息提示,先说转,我们是从0一直增加,一说停止肯定是到一个角度不动了,假如是1460角度停止。
换算成圈数就是360度*4圈 +20度,就是赚了4圈多20度。
既然是停止,我们只要到1460时清除间隔函数就可以了,clearInteval的使用,传入间隔id。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //停止时的角度 var stopdeg=1460; //监听点击事件 zhizhen.onclick=function(){ dbox=setInterval(dong,dtime); }; function dong(){ deg+=cc; if(deg>stopdeg){ clearInterval(dbox); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
六.停止角度转为圈数+角度
我们上面也提到了1460就是4圈+20度,这个停止角度如此表示之后
//旋转基本圈数 var quan=4; //多余角度 var odeg=20; //停止时的角度 var stopdeg=quan*360+odeg;
采用这种设置以后,我们可以自定义旋转圈数,比如基本圈数是6圈,同样停止额外角度也可自定义,比如是80度:
//旋转基本圈数 var quan=6; //多余角度 var odeg=80; //停止时的角度 var stopdeg=quan*360+odeg;
下面是修改后的代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=6; //多余角度 var odeg=80; //停止时的角度 var stopdeg=quan*360+odeg; //监听点击事件 zhizhen.onclick=function(){ dbox=setInterval(dong,dtime); }; function dong(){ deg+=cc; if(deg>stopdeg){ clearInterval(dbox); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
六.奖项依据
还是上面的延续,我们设置是6圈+80度,其实6圈我们不用考虑,只是让用户感觉在抽奖的假象,这个80才是我们真实考虑的东西,因为他代表在转盘上指针停在了哪里,要通过停在的位置弹出获奖信息:
80度的位置和其实参考如图所示。
毫无疑问,0-6这7个奖项在0-360之间各占一定的区间,我们需要测量出来,例如:
0等奖:0-50度
6等奖:51-101度 等等一次类推
我们选择的图毫无疑问是失败的,若果是6等分,我们直接就算出来了(360*6),可是7份(360/7尴尬)的就要实际测量:
//区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ];
我们奖项和角度对应关系,我们现在是80度,那么就是6等奖
六.奖项判断
我们会在80度位置停止,我们的依据就是上面的数组,我们要写一个判定函数,去自动判断是几等奖,这样就非常的方便了,我们把80改为150也许自己判定结果。
//奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<jiang[i][1]){ res=jiang[i][2]; }; }; return res; };
我们在停止时弹出提示
if(deg>stopdeg){ clearInterval(dbox); alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; };
修改后全部代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=6; //多余角度 var odeg=80; //停止时的角度 var stopdeg=quan*360+odeg; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //监听点击事件 zhizhen.onclick=function(){ dbox=setInterval(dong,dtime); }; function dong(){ deg+=cc; if(deg>stopdeg){ clearInterval(dbox); alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
七.随机奖项生成
80度也就是6等奖,这个80度我们写死是不对的,应该产生一个0-360随机度数,这样每次抽奖就会随机中奖了,针对随机数的生成,是有固定写法的,比如生成0-8的随机数,那么就是:
var odeg=Math.floor(Math.random()*10);
0-360就是照猫画虎:
var odeg=Math.floor(Math.random()*361);
修改后整体程序:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=4; //多余角度 var odeg=Math.floor(Math.random()*361); //停止时的角度 var stopdeg=quan*360+odeg; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //监听点击事件 zhizhen.onclick=function(){ dbox=setInterval(dong,dtime); }; function dong(){ deg+=cc; if(deg>stopdeg){ clearInterval(dbox); alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
八.重复性抽奖
//监听点击事件 zhizhen.onclick=function(){ deg=0; odeg=Math.floor(Math.random()*361); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); };
只要每次点击,对初始化角度,随机角度和停止角度重新赋值即可。
我们快速点击指针,发现转的越来越快?
因为每次点击都会生成一个间隔函数,我们要判断当前是不是在抽奖中,如果处在抽奖中,点击是不会触发间隔函数的。
//是否在动画中 var able=false;
在开启后转为true,表示抽奖中
function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); able=false; alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; }
点击判断是否抽奖中
zhizhen.onclick=function(){ if(!able){ deg=0; odeg=Math.floor(Math.random()*361); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; };
全部代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=4; //多余角度 var odeg=Math.floor(Math.random()*361); //停止时的角度 var stopdeg=quan*360+odeg; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<=jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //是否在动画中 var able=false; //监听点击事件 zhizhen.onclick=function(){ if(!able){ deg=0; odeg=Math.floor(Math.random()*361); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; }; function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); able=false; alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
九.抽奖次数限制
到上面,我们已经和参考效果几乎一样了,我们结合实际,一般用户只有3次机会,其实机会应该在数据库中,我们这里只是模拟处理,既然是限制次数,我们就要设置存放次数的变量:
//可用次数 var cishu=3;
每次点击监听可用次数:
//监听点击事件 zhizhen.onclick=function(){ if(!able){ if(cishu==0){ alert("次数耗光,等待次啊次机会!"); }else{ cishu-=1; deg=0; odeg=Math.floor(Math.random()*361); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; }; };
完整代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=4; //多余角度 var odeg=Math.floor(Math.random()*361); //停止时的角度 var stopdeg=quan*360+odeg; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //可用次数 var cishu=3; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<=jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //是否在动画中 var able=false; //监听点击事件 zhizhen.onclick=function(){ if(!able){ if(cishu==0){ alert("次数耗光,等待次啊次机会!"); }else{ cishu-=1; deg=0; odeg=Math.floor(Math.random()*361); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; }; }; function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); able=false; alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
十.概率设置
中奖概率我们都听过,比如冰红茶,写着
1等奖 0.0008%
2等奖 0.05%
幸运奖 3.2%
我们实例有7个奖项,设置概率如下:
0 0.938%
1 0.018%
2 0.014%
3 0.012%
4 0.008%
5 0.006%
6 0.004%
和是1就对了,我们开始跳出原有思维,我们如何应用上我们的概率?
我们现在有1000份,其中0-6 所对应份数就是上面乘以1000。
那么我们就建立这样一个长度是1000的数组,对0-6进行存放
var gailv=[[938,"未中奖"],[18,"6等奖"],[14,"5等奖"],[12,"4等奖"],[8,"3等奖"],[6,"2等奖"],[4,"1等奖"]];
var allarr=[];//长度1000,存放0-6 表示奖项 for(var i=0;i<gailv.length;i++){ for(var j=0;j<gailv[i][0];j++){ allarr.push(gailv[i][1]); }; }; var real=allarr[Math.floor(Math.random()*1000)];
real存放的就是随机奖项,概率也是来自设置。
此时我们处理和未加入概率是反的,我们是先有了奖项,就是此时已经知道用户要用什么奖了,我们接着就要让客户看见,指针要停在这个奖项区间内,
比如我们利用概率是1等奖,那么生成的角度
odeg=Math.floor(Math.random()*361);
就应该固定在:
[307,360,"1等奖"]//1等奖
307到360之间,那么随机角度生成仅仅就是一个表现形式环节,我们修改如下产生额外角度:
//通过奖项设置额外角度的表现 function set(real){ var mindeg,maxdeg; for(var i=0;i<jiang.length;i++){ if(real==jiang[i][2]){ mindeg=jiang[i][0]; maxdeg=jiang[i][1]; }; }; return mindeg+Math.floor(Math.random()*(maxdeg-mindeg+1)); };
赋值:
odeg=set(real);
全部代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;transform:rotate(0deg);} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=2; //角度,和css设置对应,初始为0 var deg=0; //变化增量 var cc=2; //旋转基本圈数 var quan=4; //多余角度 var odeg=Math.floor(Math.random()*361); //停止时的角度 var stopdeg=quan*360+odeg; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //可用次数 var cishu=3; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<=jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //是否在动画中 var able=false; //概率 var gailv=[[938,"未中奖"],[18,"6等奖"],[14,"5等奖"],[12,"4等奖"],[8,"3等奖"],[6,"2等奖"],[4,"1等奖"]]; //通过奖项设置额外角度的表现 function set(real){ var mindeg,maxdeg; for(var i=0;i<jiang.length;i++){ if(real==jiang[i][2]){ mindeg=jiang[i][0]; maxdeg=jiang[i][1]; }; }; return mindeg+Math.floor(Math.random()*(maxdeg-mindeg+1)); }; //监听点击事件 zhizhen.onclick=function(){ if(!able){ if(cishu==0){ alert("次数耗光,等待次啊次机会!"); }else{ cishu-=1; deg=0; var allarr=[];//长度1000,存放0-6 表示奖项 for(var i=0;i<gailv.length;i++){ for(var j=0;j<gailv[i][0];j++){ allarr.push(gailv[i][1]); }; }; var real=allarr[Math.floor(Math.random()*1000)]; odeg=set(real); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; }; }; function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); able=false; alert(is(odeg)); }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
十一.最终实例1
上面的全部代码已经很完整的做到了效果交互,我们进一步做优化,让代码看起来更加整洁,去除无用的操作:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=1; //角度,和css设置对应,初始为0 var deg=null; //初始角度 var sdeg=0; //由js设置默认角度 zhizhen.style.transform="rotate(" + sdeg + "deg)"; //变化增量 var cc=5; //旋转基本圈数 var quan=4; //多余角度 var odeg=null; //停止时的角度 var stopdeg=null; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //可用次数 var cishu=3; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<=jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //是否在动画中 var able=false; //概率 var gailv=[[938,"未中奖"],[18,"6等奖"],[14,"5等奖"],[12,"4等奖"],[8,"3等奖"],[6,"2等奖"],[4,"1等奖"]]; //通过奖项设置额外角度的表现 function set(real){ var mindeg,maxdeg; for(var i=0;i<jiang.length;i++){ if(real==jiang[i][2]){ mindeg=jiang[i][0]; maxdeg=jiang[i][1]; }; }; return mindeg+Math.floor(Math.random()*(maxdeg-mindeg+1));//生成min-max的随机数 }; //监听点击事件 zhizhen.onclick=function(){ if(!able){ if(cishu==0){//可用次数处理 alert("次数耗光,等待次啊次机会!"); }else{ cishu-=1;//次数减少 deg=sdeg; var allarr=[];//长度1000,存放0-6 表示奖项 for(var i=0;i<gailv.length;i++){ for(var j=0;j<gailv[i][0];j++){ allarr.push(gailv[i][1]); }; }; var real=allarr[Math.floor(Math.random()*1000)]; odeg=set(real); stopdeg=quan*360+odeg; dbox=setInterval(dong,dtime); }; }; }; //大转盘转动函数 function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); setTimeout(function(){ able=false; alert(is(odeg)); },500) }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; } }; </script> </html>
主要修改了弹出获奖信息会在500毫秒以后相应,更加的舒服。
十二.最终实例2
对比参考,人家可是开始快,最后慢的,我们既然写了,就做到他功能好的我都有,他缺的功能我也有这一步:
我们就让最后一圈慢,额外的转动最慢就可以了。
起始圈数是0,每次到达360倍数时就会增加圈数,我们对圈数计数和修改增量:
if(deg%360==0){//判断第几圈 xq+=1; if(xq==quan-1){//到最后一圈 cc=1;//增量变为1 变慢旋转 }; zhizhen.style.transform="rotate(" + deg + "deg)"; }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; };
完整实例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>幸运大转盘抽奖</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #box{ width:531px; height:531px; margin:50px auto;position:relative; background:url(images/back.png) no-repeat left top;} #zhizhen{ width:174px; height:228px; position:absolute;background:url(images/pointer.png) no-repeat left top; left:178.5px; z-index:999; cursor:pointer; top:132.5px; transform-origin:87px 133px;} </style> </head> <body> <!--幸运大转盘抽奖--> <div id="box"> <div id="zhizhen"></div> </div> </body> <script type="text/javascript"> window.onload=function(){ //幸运大转盘抽奖 //获得指针元素 var zhizhen=document.getElementById("zhizhen"); //存放间隔动画id,用来清除运动 var dbox=null; //间隔动画所用时间,表示转动快慢 var dtime=1; //角度,和css设置对应,初始为0 var deg=null; //初始角度 var sdeg=0; //由js设置默认角度 zhizhen.style.transform="rotate(" + sdeg + "deg)"; //变化增量 var cc=5; //旋转基本圈数 var quan=6; //多余角度 var odeg=null; //停止时的角度 var stopdeg=null; //区间奖项 var jiang=[ [1,51,"未中奖"], //未中奖 [52,102,"6等奖"],//6等奖 [103,153,"5等奖"],//5等奖 [154,203,"4等奖"],//4等奖 [204,251,"3等奖"],//3等奖 [252,307,"2等奖"],//2等奖 [307,360,"1等奖"]//1等奖 ]; //可用次数 var cishu=6; //奖项判定函数 function is(deg){ var res="未中奖"; for(var i=0;i<jiang.length;i++){ if(deg>=jiang[i][0] && deg<=jiang[i][1]){ res=jiang[i][2]; }; }; return res; }; //是否在动画中 var able=false; //概率 var gailv=[[938,"未中奖"],[18,"6等奖"],[14,"5等奖"],[12,"4等奖"],[8,"3等奖"],[6,"2等奖"],[4,"1等奖"]]; //开始到结束总时间 var xq=0; //通过奖项设置额外角度的表现 function set(real){ var mindeg,maxdeg; for(var i=0;i<jiang.length;i++){ if(real==jiang[i][2]){ mindeg=jiang[i][0]; maxdeg=jiang[i][1]; }; }; return mindeg+Math.floor(Math.random()*(maxdeg-mindeg+1));//生成min-max的随机数 }; //监听点击事件 zhizhen.onclick=function(){ if(!able){ if(cishu==0){//可用次数处理 alert("次数耗光,等待次啊次机会!"); }else{ cishu-=1;//次数减少 deg=sdeg; cc=5; xq=0; var allarr=[];//长度1000,存放0-6 表示奖项 for(var i=0;i<gailv.length;i++){ for(var j=0;j<gailv[i][0];j++){ allarr.push(gailv[i][1]); }; }; var real=allarr[Math.floor(Math.random()*1000)]; odeg=set(real); stopdeg=quan*360+odeg; alltime=stopdeg/cc*dtime; dbox=setInterval(dong,dtime); }; }; }; //大转盘转动函数 function dong(){ able=true; deg+=cc; if(deg>stopdeg){ clearInterval(dbox); setTimeout(function(){ able=false; alert(is(odeg)); },500) }else{ if(deg%360==0){//判断第几圈 xq+=1; if(xq==quan-1){//到最后一圈 cc=1;//增量变为1 变慢旋转 }; zhizhen.style.transform="rotate(" + deg + "deg)"; }else{ zhizhen.style.transform="rotate(" + deg + "deg)"; }; }; } }; </script> </html>
效果:
十三.九宫格大转盘
除了上面那种指针转盘,其实在类似效果中还有九宫格大转盘,也是常见效果之一,
参考:http://www.jq22.com/yanshi2022
他们的原理其实非常相似,只不过额外角度会变成额外的索引值,利用jq开发,增加速率:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>九宫格大转盘</title> <style type="text/css"> /*reset*/ *{ padding:0; margin:0} body{ height: 100%; width: 100%; font-size:12px; color:#333;} ul{ list-style:none;} /*demo*/ #lottery{width:400px;height:400px;margin:20px auto 0; position:relative;} #lottery div{width:100px;height:100px;text-align:centerfont-size:24px;color:#333; float:left;} #lottery .cent{ background:#C33;} #lottery .lottery-unit-0{ background:#CC6;} #lottery .lottery-unit-1{ background:#F99;} #lottery .lottery-unit-2{ background:#CC6;} #lottery .lottery-unit-3{ background:#F99;} #lottery .lottery-unit-4{ background:#CC6;} #lottery .lottery-unit-5{ background:#F99;} #lottery .lottery-unit-6{ background:#CC6;} #lottery .lottery-unit-7{ background:#F99;} #lottery .lottery-unit-8{ background:#CC6;} #lottery .lottery-unit-9{ background:#F99;} #lottery .lottery-unit-10{ background:#CC6;} #lottery .lottery-unit-11{ background:#F99;} #lottery div.select{background:#F0F;} #lottery .start{ position:absolute; left:100px; top:100px; height:200px; width:200px;background:#C33; font-size:30px; text-align:center; cursor:pointer; line-height:200px; color:#fff;} </style> </style> </head> <body> <!--九宫格大转盘--> <div id="lottery"> <div class="lottery-unit lottery-unit-0">1</div> <div class="lottery-unit lottery-unit-1">2</div> <div class="lottery-unit lottery-unit-2">3</div> <div class="lottery-unit lottery-unit-3">4</div> <div class="lottery-unit lottery-unit-11">12</div> <div class="cent"></div> <div class="cent"></div> <div class="lottery-unit lottery-unit-4">5</div> <div class="lottery-unit lottery-unit-10">11</div> <div class="cent"></div> <div class="cent"></div> <div class="lottery-unit lottery-unit-5">6</div> <div class="lottery-unit lottery-unit-9">10</div> <div class="lottery-unit lottery-unit-8">9</div> <div class="lottery-unit lottery-unit-7">8</div> <div class="lottery-unit lottery-unit-6">7</div> <div class="start" id="start">抽奖</div> </div> </body> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <script type="text/javascript"> $(function(){ //九宫格大转盘 var count=3;//可用次数 var i=null;//初始位置, var speed=80;//转动速度 var ok=null;//产生0-11的整数,标记中奖位置 var count=null;//总变化次数 var nowcount=null;//当前的变化位置 var n=5;//圈数 var paly=false; var xq=0; function dong(){//利用递归模拟setinterval的实现 if(nowcount>count){ setTimeout(function(){ paly=false; alert("恭喜你,中了"+eval(ok)+"等奖"); },500); }else{ nowcount+=1; if(i>10){ xq+=1; if(xq==n-1){ speed=300; }; $(".lottery-unit").removeClass("select"); $(".lottery-unit-11").addClass("select"); i=0; }else{ $(".lottery-unit").removeClass("select"); $(".lottery-unit-"+i).addClass("select"); i+=1; }; setTimeout(dong,speed); }; }; $(".start").click(function(){ if(!paly){ if(count==0){ alert("已经没有机会,下次再来!"); }else{ ok=Math.floor((Math.random()*12));//产生0-11的整数,标记中奖位置 speed=80; count=n*12+ok;//总变化次数 nowcount=0;//当前的变化位置 i=0;//初始位置, paly=true; count-=1; dong(); }; }else{ }; }); }); </script> </html>
为了增加知识量,我们的将间隔函数采用递归+延时函数的处理,中心原理几乎一致,额外的随机生成,总圈数的设置,最后开始变慢,不过这次我们是利用延时加长的设置,才用了总计数和圈计数的分别处理,同样i我们也可以利用 总计数/12 的模。
效果:
最终效果实例下载:http://www.oschina.net/code/snippet_2352644_54997
结尾要吐槽:
近期大部分都是对js知识介绍,到这时已经70篇了(第一篇是15年8月),虽然几乎没人看,不过我还是会坚持下去(最起码作为自己学习日记使用)。这一片算是改改口味,贴合实际的实例开发。
吐槽:我的博客都是文字和源码结合展示,几乎全部手打,文字+源码,那么源码我敢粘贴到博客里让你去测试,说明我肯定运行过了,运行的前面要花费多少工夫,对于搞it的你写一个效果花费时间只多不少,而且一片博客有多少源码我就不骄傲了。
我自己感觉前端的东西是十分容易测试的(新建.html文件+复制+粘贴+运行),同样只有真的有了代码,去运行了,还看到结果了,然后结合一些解释,才可能或多或少学一点点东西(发现这个效果有点意思,我喜欢,也可能突然领悟就是这个原理)。
博客其实主要作用是自己知识的总结,分享出来感觉可能会帮助那么几个人。