大转盘
为了加强跟用户的互动,很多微信公众号配置了抽奖等营销活动功能,大转盘就是最常用的一种,相比广告推广方式,大转盘互动性强、趣味性高、深受用户喜爱
页面布局:
最重要的材料就是转盘图片和指针图片,要实现页面布局,其中将转盘设置为前景,指针设置为背景,以此定义外部,内部两个容器。
代码如下:
<div id="outercont" >
<div id="outer-cont">
<div id="outer"><img src="img/activity-lottery-5.png"></div>
</div>
<div id="inner-cont">
<div id="inner"><img src="img/activity-lottery-2.png"></div>
</div>
</div>
在定义一些显示的内容区域,主要有中奖结果区,奖项设置区,活动说明区。
代码如下:
<div class="boxcontent boxyellow">
<div class="box">
<div class="title-green"><span>奖项设置:</span></div>
<div class="Detail">
<p>一等奖:iphone6 奖品数量:10 </p>
<p>二等奖:ipad6 。 奖品数量:20 </p>
<p>三等奖:ipad mini2奖品数量:100 </p>
<p>四等奖:iphone6 。奖品数量:10 </p>
<p>五等奖:ipad6 。 奖品数量:20 </p>
<p>六等奖:ipad mini 奖品数量:100 </p>
</div>
</div>
</div>
<div class="boxcontent boxyellow">
<div class="box">
<div class="title-green">活动说明:</div>
<div class="Detail">
<p>本次活动每人可以转 3 次 </p>
<p>亲,大奖转出来,祝您好运哦!! </p>
</div>
</div>
开发实现:
我们需要实现抽奖算法及中奖通知的功能。
首先定义指针转动时的中奖的角度和未中奖的角度,以便判断用户是否中奖,图中 有6个奖项区域,相应的有6个未中奖区域,奖项角度及其他变量定义如下:
var totalAngle = 0;
var steps = [];
var loseAngle = [36, 96, 156, 216, 276,336];
var winAngle = [6, 66, 126,186,246,306];
var prizeLevel;
var count = 0;
var now = 0;
var a = 0.01;
var outter, inner, timer, running = false;
bigwheel.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no;">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>幸运大转盘抽奖</title>
<link href="css/activity-style.css" rel="stylesheet" type="text/css">
</head>
<body class="activity-lottery-winning" >
<div class="main" >
<script type="text/javascript">
var loadingObj = new loading(document.getElementById('loading'),{radius:20,circleLineWidth:8});
loadingObj.show();
</script>
<div id="outercont" >
<div id="outer-cont">
<div id="outer"><img src="img/activity-lottery-5.png"></div>
</div>
<div id="inner-cont">
<div id="inner"><img src="img/activity-lottery-2.png"></div>
</div>
</div>
<div class="content" >
<div class="boxcontent boxyellow" id="result" style="display:none" >
<div class="box">
<div class="title-orange"><span>恭喜你中奖了</span></div>
<div class="Detail">
<p>你中了:<span class="red" id="prizelevel" ></span></p>
<p class="red" id="red">你可向公众号发送【中奖】查询您的中奖结果! </p>
</div>
</div>
</div>
<div class="boxcontent boxyellow">
<div class="box">
<div class="title-green"><span>奖项设置:</span></div>
<div class="Detail">
<p>一等奖:iphone6 奖品数量:10 </p>
<p>二等奖:ipad6 。 奖品数量:20 </p>
<p>三等奖:ipad mini2奖品数量:100 </p>
<p>四等奖:iphone6 。奖品数量:10 </p>
<p>五等奖:ipad6 。 奖品数量:20 </p>
<p>六等奖:ipad mini 奖品数量:100 </p>
</div>
</div>
</div>
<div class="boxcontent boxyellow">
<div class="box">
<div class="title-green">活动说明:</div>
<div class="Detail">
<p>本次活动每人可以转 3 次 </p>
<p>亲,大奖转出来,祝您好运哦!! </p>
</div>
</div>
</div>
</div>
</div>
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/alert.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
window.requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60)
}
})();
var totalAngle = 0;
var steps = [];
var loseAngle = [36, 96, 156, 216, 276,336];
var winAngle = [6, 66, 126,186,246,306];
var prizeLevel;
var count = 0;
var now = 0;
var a = 0.01;
var outter, inner, timer, running = false;
function countSteps() {
var t = Math.sqrt(2 * totalAngle / a);
var v = a * t;
for (var i = 0; i < t; i++) {
steps.push((2 * v * i - a * i * i) / 2)
}
steps.push(totalAngle)
}
function step() {
outter.style.webkitTransform = 'rotate(' + steps[now++] + 'deg)';
outter.style.MozTransform = 'rotate(' + steps[now++] + 'deg)';
outter.style.oTransform = 'rotate(' + steps[now++] + 'deg)';
outter.style.msTransform = 'rotate(' + steps[now++] + 'deg)';
if (now < steps.length) {
requestAnimFrame(step)
} else {
running = false;
setTimeout(function() {
if (prizeLevel != null) {
var levelName= new Array("", "一等奖", "二等奖", "三等奖", "四等奖", "五等奖", "六等奖")
// var levelName = "";
// if (prizeLevel == 1) {
// levelName = "一等奖"
// } else if (prizeLevel == 2) {
// levelName = "二等奖"
// } else if (prizeLevel == 3) {
// levelName = "三等奖"
// } else if (prizeLevel == 4) {
// levelName = "四等奖"
// } else if (prizeLevel == 5) {
// levelName = "五等奖"
// } else if (prizeLevel == 6) {
// levelName = "六等奖"
// }
$("#prizelevel").text(levelName[prizeLevel]);
$("#result").slideToggle(500); //显示中奖结果
$("#outercont").slideUp(500) //隐藏转盘
} else {
alert("亲,继续努力哦!")
}
},
200)
}
}
function start(deg) {
deg = deg || loseAngle[parseInt(loseAngle.length * Math.random())];
running = true;
clearInterval(timer);
totalAngle = 360 * 1 + deg;
steps = [];
now = 0;
countSteps();
requestAnimFrame(step)
}
window.start = start;
outter = document.getElementById('outer');
inner = document.getElementById('inner');
i = 10;
$("#inner").click(function() {
if (running) return;
if (count >= 3) {
alert("您已经抽了 3 次奖,不能再抽了,下次再来吧!");
return
}
//没有获得中奖json返回,让用户退出
if (prizeLevel != null) {
alert("亲,你不能再参加本次活动了喔!下次再来吧~");
return
}
$.ajax({
url: "data.php",
dataType: "json",
data: {
openid: "o7MB9jg5Oi_VNIZzeBX9mWPZP3Y4",
time: (new Date()).valueOf()
},
beforeSend: function() {
running = true;
timer = setInterval(function() {
i += 5;
outter.style.webkitTransform = 'rotate(' + i + 'deg)';
outter.style.MozTransform = 'rotate(' + i + 'deg)'
},
1)
},
success: function(data) {
//达到最大抽奖次数
if (data.error == "max_times") {
alert("您已经抽了 3 次奖,不能再抽了,下次再来吧!");
count = 3;
clearInterval(timer);
return
}
//已中奖
if (data.error == "ok") {
$("#tel").val(data.tel);
$("#red").text(data.message);
// alert(data.message);
count = 3;
clearInterval(timer);
prizeLevel = data.prizelevel;
start(winAngle[data.prizelevel - 1]);
return
}
//未中奖则累加次数
running = false;
count++
prizeLevel = null;
start()
},
//未获取json返回时
error: function() {
// alert(data.message);
prizeLevel = null;
start();
running = false;
count++
},
timeout: 4000
})
})
});
//保存用户中奖信息,手机号
$("#save-btn").bind("click",
function() {
var btn = $(this);
var tel = $("#tel").val();
if (tel == '') {
alert("请输入手机号");
return
}
var submitData = {
openid: 20,
// code: $("#sncode").text(),
tel: tel
};
$.post('data.php', submitData,
function(data) {
if (data.error == "ok") {
alert(data.message);
$("#result").slideUp(500); //隐藏中奖结果
$("#outercont").slideToggle(500) //显示转盘
return
}
},
"json")
});
</script>
</body>
</html>
data.php
<?php
// $openid = $_GET["openid"];
// $candidate = $_GET["candidate"];
// logger2($_GET['token']);
// logger2($_GET['t']);
// // error 是否中奖 ok 中奖,
// // message 提示说明
// // prizelevel 奖品等级
// logger2($_GET['time']);
// logger2($_GET['openid']);
// logger2($_GET['tel']);
if (rand(1, 1000) <= 400){
//将中奖记录写入数据库
// logger2($_GET['time']);
// logger2($_GET['openid']);
// logger2($_GET['tel']);
echo '{
"error": "ok",
"message": "奖品为iPhone5",
"prizelevel": "2",
"success": "y"
}';
}
function logger2($log_content)
{
if(isset($_SERVER['HTTP_BAE_ENV_APPID'])){ //BAE
require_once "BaeLog.class.php";
$logger = BaeLog::getInstance();
$logger ->logDebug($log_content);
}else if (isset($_SERVER['HTTP_APPNAME'])){ //SAE
sae_set_display_errors(false);
sae_debug($log_content);
sae_set_display_errors(true);
}else {
$max_size = 100000;
$log_filename = "log.xml";
if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
}
}
?>
整体index.php代码如下:
<?php
/*
CopyRight 2018 All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
}else{
$wechatObj->valid();
}
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if($tmpStr == $signature){
return true;
}else{
return false;
}
}
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$this->logger("R ".$postStr);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE)
{
case "event":
$result = $this->receiveEvent($postObj);
break;
case "text":
$result = $this->receiveText($postObj);
break;
}
$this->logger("T ".$result);
echo $result;
}else {
echo "";
exit;
}
}
private function receiveEvent($object)
{
$content = "";
switch ($object->Event)
{
case "subscribe":
$content = "欢迎关注 德强1012 ";
break;
case "unsubscribe":
$content = "取消关注";
break;
}
$result = $this->transmitText($object, $content);
return $result;
}
private function receiveText($object)
{
$keyword = trim($object->Content);
$category = substr($keyword,0,6);
$code = trim(substr($keyword,6,strlen($keyword)));
switch ($category)
{
case "会员":
$content[] = array("Title" =>"会员卡",
"Description" =>"点击图片领取会员卡",
"PicUrl" =>"http://pic2.ooopic.com/01/38/77/75bOOOPICea.jpg",
"Url" =>"http://1.dq095.applinzi.com/91_membercard/member.php?openid=".$object->FromUserName);
break;http:
case "预约":
$content[] = array("Title" =>"预约口腔医生",
"Description" =>"点击图片开始预约",
"PicUrl" =>"http://pic4.nipic.com/20091021/3320206_171831027464_2.jpg",
"Url" =>"http://1.dq095.applinzi.com/92_order/order.php?openid=".$object->FromUserName);
break;
case "相册":
$content[] = array("Title" =>"产品相册",
"Description" =>"点击图片开始预约",
"PicUrl" =>"http://img2.imgtn.bdimg.com/it/u=3675030458,1339124782&fm=26&gp=0.jpg",
"Url" =>"//1.dq095.applinzi.com/93_album/1/huxing.php");
break;
case "照片":
$content[] = array("Title" =>"产品相册",
"Description" =>"点击图片开始预约",
"PicUrl" =>"http://pic.90sjimg.com/back_pic/u/00/02/82/06/561c95213aaa4.jpg",
"Url" =>"http://1.dq095.applinzi.com/93_album/2/examples/jquery-mobile-2.html");
break;
case "转盘":
$content[] = array("Title" =>"大转盘",
"Description" =>"大奖等你来拿哦",
"PicUrl" =>"http://www.96815.com.cn/images/kdlksx4Sd/cxxx/xscx/2017/5/11/85a9d876-0e9c-4a2d-aad8-8a7f365b4c98.jpeg",
"Url" =>"http://1.dq095.applinzi.com/94_bigwheel/index.php");
break;
default:
$content = "";
break;
}
if(is_array($content)){
$result = $this->transmitNews($object, $content);
}else{
$result = $this->transmitText($object, $content);
}
return $result;
}
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $result;
}
private function transmitNews($object, $arr_item)
{
if(!is_array($arr_item))
return;
$itemTpl = " <item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
";
$item_str = "";
foreach ($arr_item as $item)
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";
$result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item));
return $result;
}
private function logger($log_content)
{
}
}
?>