先上效果圖
序
? ? ? ?上來先一個對不起,標題黨了,本來是打算擼一個原生版本的,但是考慮到安全性和可控性,選擇了用h5實現,不然出個什么bug中了十個iphone X,這個鍋太重,背不動。gif圖由于被簡書自動加快,真實效果比較平緩正常。
實現
? ? ? ?九宮格抽獎,后臺返回八個獎品信息,排列順序如圖3-1所示,獲取到獎池數據后,遍歷數組,添加八個獎品圖 + 一個按鈕圖進div
for(var i=length;i<=(allNumber);i++){
if (i == allNumber) {
$("#checkDivId").append("<img style='background:#FF8082;width:" + onegiftWidth + "px; height:" + onegiftWidth + "px;border-radius: 8px;' src=" + centerCheckimgSrc + " class='checkAction'></img>");
}else{
$("#checkDivId").append("<img style='background:#FFFFFF;width:" + onegiftWidth + "px;height:" + onegiftWidth + "px;border-radius: 8px;' src=" +daysJoyAr[i].url +">" + "</img>");
}
}
children = $("#checkDivId").children('img');
width = children.eq(0).width() || 0;
height = children.eq(0).height() || 0;
//元素初始化
$("#checkDivId").css({
position:'relative',
width:col * width + (col-1) * spacing,
height:row * height + (row-1) * spacing
});
children.css({
position:'absolute'
});
if(line == 0){
initOne();
}else{
initTwo();
}
//初始化函數
//此時分成4個部分,上、右、下、左
//上: 0 ~ col-1
//右: col ~ col+line
//下: col+line+1 ~ 2*col+line-1
//左: else
//如果只有兩行
//此時分成4個部分,上、右、下、左
function initOne(){
children.each(function(index){
if(index >=0 && index <= (col-1)){
$(this).css({
top:0,
left: index * width + index * spacing
});
}else{
$(this).css({
bottom:0,
right: index%col*width
});
}
});
}
//如果大于兩行
function initTwo(){
children.each(function(index){
//col 列數 lin 除去上下兩行的行數 此處為1
if(index >=0 && index <= (col-1)){ //0~2
$(this).css({
top:0,
left: index * width + index * spacing
});
}else if(index >= col && index <= (col+line-1)){ //3~3
$(this).css({
top:((index+1-col))*(height+spacing),
right: 0
});
}else if(index >= (col+line) && index <= (2*col+line-1)){ //4~6
$(this).css({
bottom:0,
right:(index-((col+line)))*(width+spacing)
});
}else if(index == 7){
$(this).css({
left:0,
top:(index-(2*col+line-1))*(height+spacing)
});
}else{
$(this).css({ //中心抽獎按鈕
left:width + spacing,
top:width + spacing
});
}
});
}
? ? ? ?考慮到安全問題,抽獎結果肯定是由服務器返還,所以當點擊中間的抽獎按鈕時,調用后臺抽獎接口,返回抽獎結果。假設抽獎轉盤轉動時間為三秒,在三秒內必須拿到中獎獎品,當網絡不順暢,或者后臺程序報錯時,給用戶彈窗,程序異常并強行刷新頁面。
? ? ? ?前端要做的是在拿到結果后讓轉盤停在對應的位置上,這一點是關鍵。簡單的代碼實現如下所示。
//取一個隨機整數模擬后臺接口返回的中獎獎品id
var random = parseInt(10*Math.random());
//遍歷圖3-1中的獎池數組,找到對應中獎的獎品
for (var giftindex = 0;giftindex < checkJoyArr.length;giftindex++) {
if (checkJoyArr[giftindex].id == random) {
winlocalIndex = giftindex;//中獎獎品的索引
memberPrizeId = random;//中獎獎品的id
break;
}
}
動畫效果
? ? ? ?轉盤需要經歷 加速--->勻速--->減速--->停止 這四個階段。初始位置從索引為0的獎品開始,調用speedUp()函數,當速度到達某一值時,勻速運動1s,之后減速,減速一圈后,開始找中獎獎品索引,當ix == winlocalIndex時(ix為當前選中的商品索引),動畫結束,彈窗提示用戶中獎。幾個重要的函數如下:
var ix = 0; //初始位置
var stop ;
flg = false; //抽獎是否正在運行
/*
加速度公式
v1 = v0 + a*t;注意加速度的v代表時間
此時的t可以我們自己定義,所以是常量,所以只需要求a的值
*/
//加速
function speedUp(){
runner(ix);
if(v <= 120){
clearTimeout(stop);
v = 120;
t = 5.0;
uniform(); //跳轉到勻速
}else{
t++;
v = v0 + a*t;
stop = setTimeout(speedUp,v);
}
}
//勻速
function uniform(){
stop = setTimeout(uniform,v);
if(t == time/50){
clearTimeout(stop);
t = 0.0;
speedDown();//跳轉到減速
}else{
t++;
}
runner(ix);
}
//減速
function speedDown(){
var stop3 = setTimeout(speedDown,v);
if(v >= 500){
v = 500;
if(ix == winlocalIndex){
children.removeClass('on').eq(ix).addClass('on');
clearTimeout(stop3);
setTimeout(function(){
options.end(winlocalIndex);
flg = false;
},300)
winlocalIndex = 20;
return;
}
}else{
t++;
v = v - a*t;
}
runner(ix);
}
function runner(i){
children.removeClass('on').eq(ix).addClass('on');
i++;
if(i == allNumber){
ix = 0;
}else{
ix = i;
}
}
? ? ? ?至此幾個重要的地方基本寫完了,功能不難,就是寫的過程中比較煩,特別是布局,分分鐘想哭。由于項目中業務邏輯比這個稍微復雜了一點。有七天一次免費抽獎,用完免費抽獎機會后才扣金幣,右上角的點擊刷新獎池等,所以,過兩天剝離出一個demo來。
結語
? ? ? ?這兩天交接工作,不算太忙,準備好好梳理一下前段時間的幾個h5功能,但是寫的過程中發現,好多東西不知道怎么去描述,接觸h5也已經一年時間,特別是前段時間公司立項了幾個小游戲,研究了一段時間的白鷺引擎,看了兩周混合開發框架weex,也由最開始的抵觸慢慢到接受,技術終究是要為產品服務的。
? ? ? ?還有這周末就要飛重慶了,那個我心心念念的地方,不知道前面等待著我的會是什么,希望工作不會太難找。但行好事,莫問前程,祝我好運。。。。