使用javascript、css、jquery和php实现转盘抽奖
本课程由
jayki
发布在
实验楼
,详细教程及在线练习地址:
PHP - 转盘抽奖
一、实验简介
现在许多网站都会在节假日或庆典的时候举行一些抽奖活动吸引用户。抽奖活动的类型有多种,有转盘抽奖,翻牌抽奖等等。实现方式大多都是由 flash 或 javascript 实现。本项目使用 javascript、html、css、jquery和 php 实现一个转盘抽奖,javascript 实现转盘转动效果,jquery 实现与后台异步通信,php 则实现后台的奖品抽奖。
转盘抽奖大致效果如图1所示:
二、准备工作
打开终端窗口,使用如下命令下载所需图片和 jquery 文件:
git clone http://git.shiyanlou.com/shiyanlou/zhuanpan
进入下载目录:
cd zhuanpan
三、实现九宫格样式
PS:熟悉 html 和 css 的可以跳过这部分,直接看下面完整的 html 代码和 css 代码。
1. HTML 部分
首先用 html 实现如上图1所示的转盘抽奖的九宫格样式。创建一个空 html 文件命名为 index.html,写入如下代码:
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>zhuanpan</title>
</head>
<li><img src="img1.jpg" /></li>
<li><img src="img2.jpg" /></li>
<li><img src="img3.jpg" /></li>
<li><img src="img4.jpg" /></li>
<li><img src="btn.jpg" /></li>
<li><img src="img1.jpg" /></li>
<li><img src="img2.jpg" /></li>
<li><img src="img3.jpg" /></li>
<li><img src="img4.jpg" /></li>
</body>
</html>
打开浏览器,显示如下:
2. CSS 部分
首先为 div 增加长宽属性,由于每个图片大小为 129px*59px,div 长度要包含三个图片的长度 129px*3=387px,div 宽度也要包含三个图片的宽度 59px*3=177px,另外还有图片间的间距,所以 div 长度可以设置为 500px,宽度设置为 250px。
另外将 div 设置居中显示,并显示边框。为 div 设置样式的 css 代码如下:
div{
margin: 100px auto 0px; // 居中
width:500px;
height:250px;
border:3px solid black; // 边框
然后为包含 img 的 li 元素设置样式。首先将 li 元素设置为向左浮动(float:left),长度、宽度设置为图片的长宽大小,另外加上一个黑色边框,设置图片间的间距。
li{
width:129px;
height:59px;
border:3px solid black;
float:left; // 向左浮动
margin:8px 0 0 8px; // 设置图片间的间距
list-style:none;
打开浏览器,显示如下:
中间点击抽奖那张图片不是显示奖品信息,而是看做一个按钮,我们可以将中间图片的边框设置为红色,以示区别。
为包含这个图片的li元素加上 class="btn",然后增加样式代码:
<!--增加class="btn"-->
..........
<li><img src="img4.jpg" /></li>
<li class="btn"><img src="btn.jpg" /></li>
<li><img src="img1.jpg" /></li>
..........
// 样式文件
.btn{
border:3px solid red; // 设置为红色边框
cursor:pointer; // 设置光标类型为指针
最后我们还要设置一个样式,就是当转盘转到一张图片上时显示的样式。我们可以设置当转盘转到某张图片上时,该包含该图片的 li 元素边框为红色。
那转动时怎样将样式加到元素上呢,这里借助 class 实现。当转到某张图片上时,为包含该图片的 li 元素增加名为 cur 的 class,cur 类的样式如下:
.cur{
border:3px solid red; // 设置为红色边框
这样我们的 html 代码基本 ok 了,完整代码如下:
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>zhuanpan</title>
<style type="text/css">
margin: 100px auto 0px;
width:500px;
height:250px;
border:3px solid black;
width:129px;
height:59px;
border:3px solid #000;
float:left;
margin:8px 0 0 8px;
list-style:none;
.btn{
border:3px solid red;
cursor:pointer;
.cur{
border:3px solid red;
</style>
</head>
<li><img src="img1.jpg" /></li>
<li><img src="img2.jpg" /></li>
<li><img src="img3.jpg" /></li>
<li><img src="img4.jpg" /></li>
<li class="btn"><img src="btn.jpg" /></li>
<li><img src="img1.jpg" /></li>
<li><img src="img2.jpg" /></li>
<li><img src="img3.jpg" /></li>
<li><img src="img4.jpg" /></li>
</body>
</html>
四、javascript 实现转动效果
下面我们用 javascript 来实现转盘转动效果。大家应该都看见过转盘效果,先是慢慢转动,然后加速稳定,最后停在抽中的奖品上。那 javascript 怎么来实现这个效果呢,答案是使用 javascript 定时器函数:setTimeout() 。
首先来看下 setTimeout() 函数的定义:
setTimeout(code,millisec)
code:要调用的函数后要执行的 JavaScript 代码串。
millisec:在执行代码前需等待的毫秒数。
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式,并且只执行一次。
我们可以通过设置 setTimeout() 函数的第二个参数实现转动的快慢。第一个参数实现转动到图片上,为包含该图片的 li 元素增加样式,还记得前面所说的 cur 类样式吗,现在用到了。
为了方便定位 li 元素,我们可以为每个li元素增加id,如下代码所示:
......
<li id="c1"><img src="img1.jpg" /></li>
<li id="c2"><img src="img2.jpg" /></li>
<li id="c3"><img src="img3.jpg" /></li>
<li id="c8"><img src="img4.jpg" /></li>
<li class="btn"><img src="btn.jpg" /></li>
<li id="c4"><img src="img1.jpg" /></li>
<li id="c7"><img src="img2.jpg" /></li>
<li id="c6"><img src="img3.jpg" /></li>
<li id="c5"><img src="img4.jpg" /></li>
......
我们为每个 li 元素增加了字符 c 加上数字序号的 id,但 id 并不是按照元素从上到下的顺序来的,这是因为是按照转动顺序来的。
$('#c1').addClass('cur');
当然,转动过程不光要为该 li 元素增加 cur 类,还需要删除它前面一步 li 元素的 cur 类。
下面我们来考虑怎么用 javascript 实现整个转动过程。
这里将整个转动过程需要经过的每个元素保存在一个数组中,数组中每个元素同时也是一个数组,保存 li 元素的 id 和 setTimeout() 函数需要设置的毫秒数。
另外还需要一个变量(current)记录当前执行到哪一步。
代码如下所示:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
// 整个转动过程所需的步骤
var step = [
['c1',0], // 第一个元素特殊设置
['c1', 500],
['c2', 400],
['c3', 300],
['c4', 200],
['c5', 200],
['c6', 200],
['c7', 200],
['c8', 200],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 200],
['c3', 300],
['c4', 300],
['c5', 300],
['c6', 300],
['c7', 300],
['c8', 300],
['c1', 400],
['c2', 400],
['c3', 400],
['c4', 400],
['c5', 400],
['c6', 400],
['c7', 400],
['c8', 400]
// 记录当前步数,即step数组的下标
var current = 1;
// 设置样式和重新设置定时器
function run(){
// 删除之前设置的cur类
$('#'+step[current-1][0]).removeClass('cur');
// 为当前元素设置cur类
$('#'+step[current][0]).addClass('cur');
// 判断step数组所有步骤是否已经走完
if(current == step.length - 1){
alert("over");
window.location.reload();
}else{
// 重新设置定时器
setTimeout('run()', step[current][1]);
current++;
</script>
下面我们来看看效果怎么样。首先将上面的 js 代码添加到 index.html文件中 </div> 的后面,并且为中间的按钮添加一个单击事件。
<li class="btn"><img src="btn.jpg" onclick="run();"/></li>
打开浏览器,点击按钮,转盘已经开始转动,转盘效果已经实现了。
上面 step 数组第一个元素特殊设置需要说明一下,因为刚开始执行 run 函数时,执行到 $('#'+step[current-1][0]).removeClass('cur'); 这一步时,此时还没 li 元素被加上 cur 类。因此将 current 初始值设置为 1,并且 step 前两个元素都是指向第一个 li 元素。这样 $('#'+step[current-1][0]).removeClass('cur'); 和 $('#'+step[current][0]).addClass('cur'); 操作的都是 id=’c1’ 的 li 元素,不会影响到其他元素。
另外,上面的转盘每次都会转到最后一张图片上停止,那么下面来设置让转盘停到指定的图片上。
// 判断step数组所有步骤是否已经走完
if(current == step.length - 1){
alert("over");
window.location.reload();
我们是通过上面的代码来判断是否结束的,那么我们可以通过修改上面的代码实现让转盘停止到指定的图片上。
// 判断是否结束
if(step.length - current - 1 + 2 == 8){
alert("over");
window.location.reload();
其中 8 表示总共图片数量(不包括按钮)。打开浏览器,点击按钮发现停在了第二张图片上了。
上面代码中的 2 和 8,我们用全局变量表示。变量 data 表示要求停到哪张图片上,变量 total 表示图片总量(不包括按钮)。修改代码如下:
var data = 1; // 指定需要停在图片的序号
var total = 8; // 图片总量(不包括按钮)
..................
// 判断是否结束
if(step.length - current - 1 + data == total){
alert("over");
window.location.reload();
至此,转动效果已经完成了。
五、PHP 实现奖品抽奖
下面我们要用 PHP 代码实现每个奖品的不同抽奖概率,假设三等奖的概率为 1/30,二等奖的概率为 1/60,一等奖的概率为 1/90,下面直接给出 php 代码:
$category = 3; // 奖品种类数
$lucknum = 0; // 幸运数字
// 每个奖品依次中奖的概率
$probability = array(
10, // 三等奖
20, // 二等奖
30, // 一等奖
// 奖品名称
$prizename = array(
'third prize',
'second prize',
'first prize',
// 随机选择对哪个奖品种类进行抽奖
$caterandom = mt_rand(0, $category - 1);
// 对之前随机选择的奖品种类进行抽奖
$random = mt_rand(0, $probability[$caterandom]);
$probability 数组元素与 $prizename 数组元素是对应的。
下面详细说下抽奖过程:
-
首先 $caterandom = mt_rand(0, $category - 1); 随机从三个奖品种类中选择一个,这样每个奖品被选到的概率为1/3。
-
之后 $random = mt_rand(0, $probability[$caterandom]); 对选到的奖品种类在指定的数字之间随机选取一个数字。假如第一步选到的奖品种类是三等奖,$category 即为0,$probability[$caterandom] 即为 10,mt_rand(0,10) 会在 0 到 10 之间(不包含10)选择一个数字,这样随机得到幸运数字 0($lucknum = 0;)的概率为 1/10。这样抽到三等奖的概率为 (1/3) * (1/10) = 1/30。
-
最后根据随机获得的数字返回相应的信息给前端js,前端js根据后台传输的信息实现转盘转动效果并设置停止在哪张图片上和提示信息。
完整 php(index.php)代码如下所示:
<?php
$category = 3; // 奖品种类数
$lucknum = 0; // 幸运数字
// 每个奖品依次中奖的概率
$probability = array(
10, // 三等奖
20, // 二等奖
30, // 一等奖
// 奖品名称
$prizename = array(
'third prize',
'second prize',
'first prize',
// 奖品图片在页面上的序号,返回给前端需要
$prizecode = array(
3, // 三等奖图片,也可以是6
2, // 二等奖图片,也可以是7
1, // 一等奖图片,也可以是4
// 随机选择对哪个奖品种类进行抽奖
$caterandom = mt_rand(0, $category - 1);
// 对之前随机选择的奖品种类进行抽奖
$random = mt_rand(0, $probability[$caterandom]);
if($random == $lucknum){
// 如果抽中,返回奖品名称和奖品图片在页面上的序号
$data = array(
$prizename[$caterandom],
$prizecode[$caterandom],
// 以json格式返回给前端js
echo json_encode($data);
}else{
// 未抽中,返回谢谢参与文字和图片的序号
$data = array(
'Thank you!',
echo json_encode($data);
六、使用 ajax 与后端通信
前面已经说过前端 js 实现转盘转动效果和后端 php 实现奖品抽奖了。但是现在前端还没法和后端相互通信,下面就来讲解前后端通信方法。
我们这里使用 jquery 的 ajax 来实现。这里使用 jquery 的原因是 jquery 在异步提交方面封装的很好,而直接用 AJAX 非常麻烦。另外使用 jquery 大大简化了我们的操作,而且不用考虑浏览器的差异。
jquery 中 ajax 的一般格式如下所示:
$.ajax({
url: url ,
type: 'GET',
data: data ,
dataType: dataType,
success: success
其中 url 参数是必需的,规定把请求发送到哪个 url。
type 参数可选,规定请求方式,默认为 GET。
data 参数可选,规定连同请求发送到服务器的数据。我们这里不需要发送数据到后端。
dataType 参数可选,规定预期的服务器响应的数据类型,默认执行智能判断(xml、json、script 或 html)。
success 参数可选,规定请求成功时执行的回调函数。
了解了 jquery 中的 ajax 后,那我们来实现前端和后端之间的通信。那么什么时候执行 ajax 方法呢?
答案是当单击抽奖按钮的时候。当单击按钮的时候,首先通过 ajax 请求后端获得这次抽奖的结果信息,根据后端返回的信息设置一些初始信息,包括指定需要停在图片的序号(data 变量)、转盘结束时弹窗显示的文字(msg 变量),然后开始调用 run() 函数执行转盘转动。
由于之前按钮上绑定的 onclick 事件处理函数是 run(),那么现在要更换为包含 ajax 请求的函数了。下面使用一个 start() 函数封装 ajax 的相关请求及处理,代码如下所示:
function start(){
$.ajax({
url: "http://127.0.0.1/index.php",
type:"GET",
dataType: "json",
success: function(d){
msg = d[0]; // 设置转盘结束时弹窗显示的文字
data = d[1]; // 设置需要停在图片的序号
run();
并将按钮的 onclick 事件处理函数更改为 start()。
<li class="btn"><img src="btn.jpg" onclick="start();"/></li>
包含 js 的完整 html(index.html) 代码如下所示:
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>zhuanpan</title>
<style type="text/css">
div{margin: 100px auto 0px;width:500px;height:250px;border:3px solid black;}
li{width:129px; height:59px; border:3px solid #000; float:left; margin:8px 0 0 8px; list-style:none;}
.btn{ border:3px solid red;cursor:pointer}
.cur{ border:3px solid red;}
</style>
</head>
<li id="c1"><img src="img1.jpg" /></li>
<li id="c2"><img src="img2.jpg" /></li>
<li id="c3"><img src="img3.jpg" /></li>
<li id="c8"><img src="img4.jpg" /></li>
<li class="btn"><img src="btn.jpg" onclick="start();"/></li>
<li id="c4"><img src="img1.jpg" /></li>
<li id="c7"><img src="img2.jpg" /></li>
<li id="c6"><img src="img3.jpg" /></li>
<li id="c5"><img src="img4.jpg" /></li>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
// 整个转动过程所需的步骤
var step = [
['c1',0], // 第一个元素特殊设置
['c1', 500],
['c2', 400],
['c3', 300],
['c4', 200],
['c5', 200],
['c6', 200],
['c7', 200],
['c8', 200],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 100],
['c3', 100],
['c4', 100],
['c5', 100],
['c6', 100],
['c7', 100],
['c8', 100],
['c1', 100],
['c2', 200],
['c3', 300],
['c4', 400],
['c5', 400],
['c6', 400],
['c7', 400],
['c8', 400],
['c1', 400],
['c2', 400],
['c3', 400],
['c4', 400],
['c5', 400],
['c6', 400],
['c7', 400],
['c8', 400]
// 记录当前步数,即step数组的下标
var current = 1;
// 指定需要停在图片的序号
var data = 5;
// 图片总量(不包括按钮)
var total = 8;
// 转盘结束时弹窗显示的文字
var msg = '';
// 设置样式和重新设置定时器
function run(){
// 删除之前设置的cur类
$('#'+step[current-1][0]).removeClass('cur');
// 为当前元素设置cur类
$('#'+step[current][0]).addClass('cur');
// 判断step数组所有步骤是否已经走完
if(step.length - current - 1 + data == total){
alert(msg);
window.location.reload();
}else{
// 重新设置定时器
setTimeout('run()', step[current][1]);
current++;
function start(){
$.ajax({
url: "http://127.0.0.1/index.php",
type:"GET",
dataType: "json",
success: function(d){
msg = d[0]; // 转盘结束时弹窗显示的文字
data = d[1]; // 指定需要停在图片的序号
run();
</script>
</body>
</html>
七、运行
由于要运行 php 代码,需要安装 nginx 服务器。
执行下面的命令安装 nginx:
sudo apt-get install nginx
执行下面的命令安装 php:
sudo apt-get update
sudo apt-get install php5-fpm
接下来修改 nginx 的配置文件,文件为 /etc/nginx/sites-available/default:
使用vim编辑器
sudo vim /etc/nginx/sites-available/default
或使用gedit编辑器
sudo gedit /etc/nginx/sites-available/default