首页 » 微信公众平台开发:从零基础到ThinkPHP5高性能框架实践 » 微信公众平台开发:从零基础到ThinkPHP5高性能框架实践全文在线阅读

《微信公众平台开发:从零基础到ThinkPHP5高性能框架实践》24.5.5 Ajax提交与转盘控制

关灯直达底部

下面实现抽奖算法及中奖通知的功能。

首先定义指针转动时中奖的角度和未中奖的角度,以便判断用户是否中奖,图中有6个奖项,相应有6个未中奖区域。奖项角度及其他变量定义如下。


1 var totalAngle  = 0;2 var steps = ;3 var loseAngle = [36, 96, 156, 216, 276, 336];4 var winAngle = [6, 66, 126, 186, 246, 306];5 var prizeLevel;6 var now = 0;7 var count = 0;8 var a = 0.01;9 var outter, inner, timer, running = false;  

用户进入抽奖界面后,点击抽奖指针,相应的代码处理如下。


 1 $("#inner").click(function { 2   if (running) return; 3   if (count >= 3) { 4     alert("达到最大抽奖次数!"); 5     return 6   } 7   $.ajax({ 8     url: "data.php", 9     dataType: "json",10     data: {11       openid: "<?php echo $_GET["openid"];?>",12       time: (new Date).valueOf13     },14     beforeSend: function {15       running = true;16       timer = setInterval(function {17         i += 518       },19       1)20     },21     success: function(data) {22       // 达到最大抽奖次数23       if (data.status == "MAX") {24         alert("您已达到最大抽奖次数!");25         count = 3;26         clearInterval(timer);27         return28       }29       // 有中奖时转盘转到相应位置30       if (data.status == "WIN") {31         $("#prizename").text(data.prizename);32         count = 3;33         clearInterval(timer);34         prizeLevel = data.prizelevel;35         start(winAngle[data.prizelevel - 1]);36         return37       }38       // 未中奖则再给机会39       running = false;40       count++41       prizeLevel = null;42       start43     },44     // 未获取JSON返回,前台处理45     error: function {46       prizeLevel = null;47       start;48       running = false;49       count++50     },51     timeout: 400052   })53 })  

点击事件发生时,页面将向data.php文件发送POST请求,将当前用户的OpenID和时间传递过去。data.php中在收到数据后将需要进行一系列的复杂处理,这些在24.5.6节中有详细的讲述下面是一个中奖情形的返回结果。


echo '{"status": "WIN", "prizename": "iPhone 5S", "prizelevel": "2"}';  

该情形表示当前已中奖,奖品等级是2,奖品为iPhone 5S。data.php将该JSON数据返回给请求页面,原页面收到数据后,第29~37行代码将进行处理,它将抽奖次数直接置为最大抽奖次数3,并且计算转盘将要旋转的角度,而这个旋转角度也就是奖项的角度,以此确保转盘停止后,指针落点无误。

当中奖数据返回中没有要中奖的标记(第38~42行)或者没有接收到返回的JSON数据时(第44~50行),转盘也需要计算旋转角度,页面将在前台累加抽奖次数,直到达到最大抽奖次数,然后提示用户抽奖次数已经用完。如果返回的JSON数据中显示已经达到最大抽奖次数,则以JSON数据优先作为判断依据(第22~28行)。

当启动转盘转动时,本次抽奖结果已经被旋转角度确定下来了,这是通过start方法实现的。该方法带有一个参数deg。如果中奖,则deg传输进来时就已经是某奖项的角度;如果没有中奖,deg直接传空,这时将随机计算出一个非奖项的角度并赋给它。start方法的实现如下。


 1 function start(deg) { 2     deg = deg || loseAngle[parseInt(loseAngle.length * Math.random)]; 3     running = true; 4     clearInterval(timer); 5     totalAngle  = 360 * 5 + deg; 6     steps = ; 7     now = 0; 8     countSteps; 9     requestAnimFrame(step)  

在start函数中,需要根据旋转角度生成本次转动的步骤,这时往往需要添加N个360°,以便在旋转N圈后落到真正的奖项区域。而这个旋转角度以数组的方式保存。其角度差需要逐渐变小,以实现减速旋转最终停下来的效果。该数组的生成代码如下。


1 function countSteps {2     var t = Math.sqrt(2 * totalAngle / a);3     var v = a * t;4     for (var i = 0; i < t; i++) {5         steps.push((2 * v * i - a * i * i) / 2)6     }7     steps.push(totalAngle)8 }  

上面代码将生成一个元素个数非常大的角度列表数组,数组存储到steps中。这里为了简便,生成了一个简化版本,如表24-9所示。

表24-9 旋转角度数组

从表24-9中可以看到,转盘将从0旋转到624.9°,每一步的旋转角度差将越来越小,直到为0,这时将停留到预先生成好的角度上。

而实现旋转的动画效果,是使用HTML5中的window.requestAnimFrame方法实现的,代码如下。


 1 window.requestAnimFrame = (function { 2   return window.requestAnimationFrame ||  3          window.webkitRequestAnimationFrame ||  4          window.mozRequestAnimationFrame ||  5          window.oRequestAnimationFrame ||  6          window.msRequestAnimationFrame || 7   function(callback) { 8     window.setTimeout(callback, 1000 / 60) 9   }10 }); 

当动画将每个旋转角度走完以后,需要将中奖结果提示给用户。没有中奖时只需要弹出一个消息框即可,而中奖时需要隐藏转盘、显示中奖区域、显示中奖结果。该部分代码如下。


 1 function step { 2     outter.style.webkitTransform = 'rotate(' + steps[now++] + 'deg)'; 3     outter.style.MozTransform = 'rotate(' + steps[now++] + 'deg)'; 4     outter.style.oTransform = 'rotate(' + steps[now++] + 'deg)'; 5     outter.style.msTransform = 'rotate(' + steps[now++] + 'deg)'; 6     if (now < steps.length) { 7         requestAnimFrame(step) 8     } else { 9         running = false;10         setTimeout(function {11             if (prizeLevel != null) {12                 var levelName= new Array("", "一等奖", "二等奖", "三等奖", "四等奖",                   "五等奖", "六等奖")13                 $("#prizelevel").text(levelName[prizeLevel]);14                 $("#result").slideToggle(500);  // 显示中奖区域15                 $("#outercont").slideUp(500)    // 隐藏转盘16             } else {17                 alert("亲,继续努力哦!")18             }19         },20         200)21     }  

最终的中奖结果页面如图24-22所示。

图24-22 大转盘中奖页面