Home » Code » php+jquery实现转盘抽奖 概率可任意调

php+jquery实现转盘抽奖 概率可任意调

php+jquery实现转盘抽奖

查看DEMO演示

转盘抽奖,炫丽的一般是flash做的。不懂flash而又不需要那么炫丽,可以简单的通过jquery来实现。网上教程有很多,跟着做了一下,也贴出来吧。要实现转盘抽奖,有两个关键点,一是让转盘或指针转起来并控制停止角度,一是概率控制。

对于转起来控制停止角度这个问题,网上各教程都是用的jqueryrotate这个jquery插件,兼容性好使用也简单,要我本人自己写也不知道怎么写好,还是拿来即可。对于概率控制,网上也一致的是这个经典算法:

function getRand($proArr) {
$result = '';
//概率数组的总概率精度
$proSum = array_sum($proArr);
//概率数组循环
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum);
if ($randNum <= $proCur) {
$result = $key;
break;
} else {
$proSum -= $proCur;
}
}
unset ($proArr);
return $result;
}

这里参数是一个概率数组,某一项的出现的概率是其概率精度/总概率精度。比如概率数组是array(‘1’=>’40’,’2’=>’60’),那么‘1’这一项出现的概率就是40/(40+60)。为什么是这个结果呢,好吧,简单的概率计算:

php经典概率算法解析

php经典概率算法解析

(原谅我为了输这分数,还去百度了一下,囧…)

对于概率数组的来源,实际应用中应该是从数据库里面取,这样方便做各种业务判断,比如某一奖项的概率除了人工干预还根据抽中次数自动变化。我这里为了显示,就写到一个数组里面,而且这找的转盘素材同一奖项还有多处出现,故用这样一个数组来存储(这里根据实际业务而定,不是重点)。

//奖项数据
$prize_arr=array(
'youpan'=>array('angle'=>array('16-40','196-220'),'prize'=>'U盘1个','v'=>10),
'money_2000'=>array('angle'=>array('46-74','170-194'),'prize'=>'2000元代金卷','v'=>5),
'chong_10'=>array('angle'=>array('80-104','226-250'),'prize'=>'10元充值卡','v'=>10),
'money_1000'=>array('angle'=>array('110-134','256-284'),'prize'=>'1000元代金卷','v'=>15),
'flower'=>array('angle'=>array('144-164','286-306'),'prize'=>'鲜花1朵,继续努力','v'=>45),
'chong_50'=>array('angle'=>array('316-340'),'prize'=>'50元充值卡','v'=>5),
'book'=>array('angle'=>array('0-10','346-359'),'prize'=>'书1本','v'=>10),
);

angel是角度,最小角度与最大角度用‘-’隔开,有多个。这个角度是控制转盘或指针最终停下来时离起点的角度,范围是0~360。根据实际素材而定,我这找的图不规则,作图的人坑爹,调了多次才得到比较精准的角度。v则是概率。

根据上面的奖项设定,通过下面的函数返回转动信息到前台:

//获得旋转信息
function getRotate($prize_arr) {
$data=array();
$option=$_GET;//根据前台的选择更改原定默认概率
foreach($prize_arr as $k=>&$v) {
$v['v']=$option[$k];
}
$prize=getPrize($prize_arr);//通过概率原理设计函数获得其中一个奖项
$angle=$prize['angle'];
shuffle($angle);//打乱角度数组
$angle=$angle[0];
$angle_arr=explode('-',$angle);
$min=$angle_arr[0];
$max=$angle_arr[1];
$angle=mt_rand($min,$max);
$data['angle']=$angle;
$data['message']=$prize['prize'];
$data['duration']=mt_rand(2,5)*1000;
$data['n']=mt_rand(3,6);//为了不那么单调,随机一下转动时间和转动圈数
echo json_encode($data);
}

至此后端的程序完毕。前端还得有个调整概率的功能,脑子里想到的就是滑动条,html5有这个特性,但样式简单也兼容性也有问题。百度了一下知道jqueryui有相关控件,但不怕笑话作为新人还没用过jqueryui,无意发现了noUiSlider这个专为不使用jqueryui实现滑动条而生的插件,短小精悍。最近又瞄了瞄BootStrap,顺手又拿来排版一下这前端页面,好吧,基本没用到它的什么东西。

现在时间凌晨1:52,夜已深,后面继续。。。

2014/5/14 23:13,继续。

对于改变概率值,上边说了使用noUiSlider,用法可以到官网查看:

$(".youpan").noUiSlider({
start:[10],//起始值
range:{//范围
'min':0,
'max':99,
},
connect:'lower',//写上左边就变色
serialization: {
lower: [
$.Link({
target: $('#youpan')//数值在哪里显示
})
],
format: {
decimals: 0,//数值保留几位小数
mark: ','
}
}
});

在页面加载函数里边给每个需要滑动的元素绑定以上事件即可。更改各项值放在一个form表单,点击开始抽奖收集表单的信息ajax发送到后台计算出具体的旋转信息,再进行转动抽奖。发送ajax的函数如下:

function getPrize() {
var result=null;
var option=$("#myform").serialize();
$.ajax({
url:"03.php",
type:"GET",
data:option,
dataType:"json",
cache:false,
async:false,//同步,否则无法把后台信息信息捕获
error:function(){
alert('出错了');
return false;
},
success:function(data){
result=data;
}
});
return result;}

接下来是关键的根据后台的信息进行转动并控制停止角度,主要是jqueryrotate的用法,详细的可以点击上边高亮的链接查看。下边也有注释:

function rotate() {
$("#start").css("cursor","pointer");
$("#start").rotate({
bind:{
click:function(){
$(this).unbind('click').css("cursor","default");//取消点击事件
var value=getPrize();
var effect=$("#select").val();
$(this).rotate({
duration:value.duration,//多少毫秒内完成转动
angle:0,//起始角度
animateTo:value.n*360+value.angle,//一共转动多少角度
easing:eval(effect),//转动动画扩展
callback:function(){//结束时的回调函数
alert(value.message);
}
})
}
}
})
}

转动动画那里,注意得eval()一下,否则得到的只是一个字符串不是动画函数。这个动画也是用的jQuery Easing这个插件,插件再借用插件,很常见的事,什么都自己写,是很不现实的,童鞋。这些动画效果用在这里有一两个动不了,不知为何。把这个rotate函数放到页面加载函数中,在页面加载完毕即可进行转动抽奖。点击之后取消点击事件,是为了防止转动过程中或者抽完一次后继续点击。当然我这里有“再来一发”就是给再绑上。具体看业务需要,怎么搞都行。

至此,一个简单的转盘抽奖就完成了,虽然简陋了点但也能满足一般的业务需要。有什么问题或者改进意见,欢迎各位看官提出。^~^

update:2015/06/17

鉴于有同学说不懂03.php里边的内容,顺便贴出来吧。按需修改。

<?php

//奖项数据
$prize_arr=array(
	'youpan'=>array('angle'=>array('16-40','196-220'),'prize'=>'U盘1个','v'=>10),

	'money_2000'=>array('angle'=>array('46-74','170-194'),'prize'=>'2000元代金卷','v'=>5),

	'chong_10'=>array('angle'=>array('80-104','226-250'),'prize'=>'10元充值卡','v'=>10),

	'money_1000'=>array('angle'=>array('110-134','256-284'),'prize'=>'1000元代金卷','v'=>15),

	'flower'=>array('angle'=>array('144-164','286-306'),'prize'=>'鲜花1朵,继续努力','v'=>45),

	'chong_50'=>array('angle'=>array('316-340'),'prize'=>'50元充值卡','v'=>5),

	'book'=>array('angle'=>array('0-10','346-359'),'prize'=>'书1本','v'=>10),

);

//根据奖项数据获得具体奖项
function getPrize($prize_arr) {
	$proSum=0;
	foreach($prize_arr as $v){
		$proSum+=$v['v'];
	}
	foreach($prize_arr as $k=>$v){
		$randNum=mt_rand(1,$proSum);//随机数
		if($randNum<=$v['v']) {
			return $v;
		}else{
			$proSum-=$v['v'];
		}
	}

}

//获得旋转信息
function getRotate($prize_arr) {
	$data=array();
	$option=$_GET;
	foreach($prize_arr as $k=>&$v) {
		$v['v']=$option[$k];
	}

	$prize=getPrize($prize_arr);

	$angle=$prize['angle'];
	shuffle($angle);//打乱

	$angle=$angle[0];

	$angle_arr=explode('-',$angle);

	$min=$angle_arr[0];
	$max=$angle_arr[1];
	$angle=mt_rand($min,$max);
	$data['angle']=$angle;
	$data['message']=$prize['prize'];
	$data['duration']=mt_rand(2,5)*1000;
	$data['n']=mt_rand(3,6);
	echo json_encode($data);
	//echo json_encode($option);

}

getRotate($prize_arr);

Update:2015/11/23

鉴于经常有人问要源代码打包,其实是只是很基本的一点东西而已,离应用于实际项目还有很长距离。

代码打包下载(引入的相关js与图片自行复制了):代码打包

17 comments

  1. 您好,我按照后台程序设置了php,也命名了03.php,但是转不起来,一点就显示“出错了”。但是链接您的03.php就没有问题。能否给一下03.php的完整代码?谢谢,万分感激

  2. 求分享源码,03.php不知道怎么创建

  3. 求如何写入数据库,万分感谢。

  4. 有源码吗 ?求源码一用谢谢 !!!!!!!!!!!!!

  5. 可以给一下源码我吗 ? 非常感谢了

  6. 能 发一份完整的 代码 给我吗 非常非常感谢 280491172@qq.com

  7. I’m really enjoying the theme/design of your website. Do you ever run into any internet browser compatibility problems?
    A few of my blog visitors have complained about my website not operating
    correctly in Explorer but looks great in Chrome.
    Do you have any ideas to help fix this issue?

    Here is my web page: Carlton

  8. Hello, its pleasant post about media print, we all be aware of media is a fantastic source
    of data.

Leave a Reply to xiaomiao Cancel reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.