开发H5项目,有时会遇到一个需求,需要制作仿制老虎机游戏抽奖的网页,这个实现步骤,如果拿现成的改来做是容易的,但是想着全靠自己做是不容易的,接下来开始讲,想不想自己做,有把握学到吗
首先创建一个网页文件,例如index.html
,制作老虎机游戏抽奖页面,源代码如下,通过修改样式里设置好背景色,还有组件的位置,再加一个抽奖按钮,写好大概逻辑,还有需要调用的一些方法
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>老虎机 Slot Machinestitle>
<style>
html{
height: 100%;
background: linear-gradient(#f50,#f55,#fff);
}
#box{
padding: 40px 0;
}
#btn1{
padding: 0.6em 2.5em;
font-size: 1em;
border-radius: 10px;
border-color: rgba(0, 0, 0, 0.4);
color: #fff;
background: linear-gradient(#eee,#f50);
}
style>
head>
<body>
<div id="box">div>
<hr/>
<div class="" style="text-align: center;">
<button id="btn1">抽奖button>
div>
<script type="module">
import SlotMachines from './slot_machines.js';//引用模块
window.onload = ()=>{
//...
}
script>
body>
html>
接着,写一个加载脚本的处理逻辑,代码如下,使用SlotMachines
对象创建前,需要先引用一个模块
//goods 这个图片是奖品,最好自己添加,至少8个,没有图可以用名称title代替
const sm = new SlotMachines({
id:'box',
cols:3,//列数,至少3个
rows:3,//行数,至少3个
goods:[{
image:'./img/b5ff4601d9679f502f8f9e737bdd7049.jpeg',
title:'谢谢回顾'
},{
image:'./img/e7b2e38c8d66613d1dd869b199031d8e.jpeg',
title:'特等奖'
},{
title:'再接再厉',
},{
image:'./img/b5ff4601d9679f502f8f9e737bdd7049.jpeg',
title:'谢谢回顾'
},{
image:'./img/e7b2e38c8d66613d1dd869b199031d8e.jpeg',
title:'一等奖'
},{
title:'再接再厉',
},{
image:'./img/e7b2e38c8d66613d1dd869b199031d8e.jpeg',
title:'二等奖'
},{
title:'恭喜发财',
}],
//设置中心框框的样式,可以加Logo背景图
styleCenter:{
color:'#fff',
textAlign:'center',
background:'url(./img/fGGGjP1ob1541164442344compressflag.jpg)',
backgroundSize:'cover',
backgroundRepeat:'no-repeat',
backgroundPosition:'center'
}
},window);
//设置按钮点击事件
document.getElementById('btn1').onclick=()=>{
sm.onStart({
//index:6,//设定抽到的奖品index,不传就是抽中随机
success:res=>{
//console.log('end',res)
let g = res.grids[res.index];
let msg;
if(g.title){
if(g.title.indexOf('奖')>=0) msg=`🙂恭喜您,中了${g.title}`;
else msg=`😔很遗憾,未中奖! \n${g.title}`;
}else msg=`抽中奖品${res.index}`;
alert(msg);
}
})
}
接下来,看上面有引用的一个模块文件
slot_machines.js
,没有的就把它新建好,在一个模块中去实现上面未实现的调用方法,代码如下
export default class SlotMachines{
constructor(object,window){
// 这里做一些初始化的工作...
}
onStart(conf={}){
// 这里做抽奖的处理逻辑和动画...
}
}
接下来,写方法的实现细节要复杂得多,如果看着比较吃力,就先收藏好,以后有时间慢慢摸索,边学边做
在构造方法constructor()
里做初始化,可以先实现绘制老虎机组件,代码如下
export default class SlotMachines{
//私有属性
#grids=[];
#activeIndex=0;
//动态设置激活样式的方法
#setActiveStyle;
constructor(object,window){
if(typeof object.id!='string') throw new Error('id is undefined')
const { document } = window;
//按自己实际需求传入,可修改对应的样式,任你千变万化,我有一定之规。
object=Object.assign({
cols:6,
rows:5,
styleBg:{
margin:'auto',
border: '2px solid #f50',
backgroundColor:'#f50',
borderRadius:'5px'
},
styleGrid:{
color:'#fff',
borderColor:'#faa',
backgroundColor:'#faa',
borderRadius:'5px'
},
styleActive:{
color:'#000',
borderColor:'#af0',
backgroundColor:'#aaff00',
},
styleCenter:{
color: '#fff',
backgroundColor:'#f50',
textAlign:'center'
},
centerText: '老虎机\nSlot Machines',
goods:[],
},object);
object.cols=Math.max(object.cols,3);
object.rows=Math.max(object.rows,3);
let box = document.getElementById(object.id);
if(box==undefined) throw new Error('element is undefined');
this.#setActiveStyle=(elem,isActive)=>{
Object.assign(elem.style,isActive ? object.styleActive : object.styleGrid);
};
let width = box.offsetWidth;
let table = document.createElement('table');
Object.assign(table.style,object.styleBg);
let borderW = 4;
let size = width/object.cols-borderW*2;
let grids = [];
let grids2 = [];
let grids3 = [];
let grids4 = [];
let childElementCount = 0;
let centerElement;
for(let i=1; i<=object.rows; i++){
let row = document.createElement('tr');
for(let j=1; j<=object.cols; j++){
let col = document.createElement('td');
let style = col.style;
if(i-1==0) grids.push({ element: col});
else if(i==object.rows) grids3.push({ element: col});
else if(j==object.cols) grids2.push({ element: col});
else if(j-1==0) grids4.push({ element: col});
else {
if(centerElement==undefined){
Object.assign(style,object.styleCenter);
col.setAttribute('colspan', object.cols-2);
col.setAttribute('rowspan', object.rows-2);
if(object.centerText) col.innerText=object.centerText;
centerElement=col;
row.appendChild(col);
}
continue;
};
style.width=size+'px';
style.height=style.width;
this.#setActiveStyle(col,false);
row.appendChild(col);
}
table.appendChild(row);
}
let grids5 = grids2.concat(grids3.reverse(),grids4.reverse());
grids=grids.concat(grids5);
const setText=(parent,text)=>{
let div = document.createElement('div');
div.innerText=text;
Object.assign(div.style,{
width:size+'px',
textAlign:'center',
overflow:'hidden',
textOverflow:'ellipsis',
whiteSpace:'nowrap'
});
parent.appendChild(div)
};
grids.forEach((g,i)=>{
let col = grids[i].element;
let style = col.style;
if(i<object.goods.length){
let g = object.goods[i];
switch(typeof g){
case 'string':
g = { title:g };
break;
case 'object':
break;
default:
throw new Error('param goods has error');
}
if(g.image) {
col.style.background=`url(${g.image})`;
col.style.backgroundSize='88%';
col.style.backgroundRepeat='no-repeat';
col.style.backgroundPosition='center';
}else if(g.title) {
setText(col,g.title);
}
grids[i].good=g;
}else{
setText(col,i+'.');
}
grids[i].id=i;
Object.assign(col.style,object.styleGrid);
style.borderWidth=borderW+'px';
});
this.#grids=grids;
box.appendChild(table);
}
onStart(conf={}){
//这里做抽奖的处理逻辑和动画...
}
}
实现开始抽奖方法onStart()
,可通过传入参数对象conf
,修改默认配置,代码如下,抽奖结果会通过回调方法succes()
返回
export default class SlotMachines{
#grids=[];
#activeIndex=0;
#setActiveStyle;
constructor(object,window){
//这里做一些初始化的工作,已实现...
}
onStart(conf={}){
if(typeof conf.success!='function') throw new Error('success is undefined')
conf=Object.assign({
index:-1,//预定奖品,默认随机
rotationNum: 3,//至少旋转的圈数
speedMull:1.5,//移动速度变化倍率
speedMax:10,//最快刷新延迟ms
speedMin:2000,//最慢刷新延迟ms
},conf);
const grids = this.#grids;
if(conf.index<0 || conf.index>=grids.length){
conf.index=Math.trunc(Math.random()*grids.length);
// console.log('index',conf.index)
}
let index=0;
let time=conf.speedMax;
let rotationNum=0;
while(time<conf.speedMin){
time*=conf.speedMull;
index++;
}
let index2=conf.index-(index%grids.length)+1;
index=this.#activeIndex;
time=conf.speedMax;
if(index2<0) index2=grids.length+index2;
const activating = (timeout) => {
setTimeout(()=>{
let preG = grids[index-1>=0 ? index-1 : grids.length-1];
let g = grids[index];
this.#setActiveStyle(preG.element,false);
this.#setActiveStyle(g.element,true);
if(rotationNum>conf.rotationNum) time*=conf.speedMull;
if(time<conf.speedMin) {
index++;
if(index>=grids.length) index=0;
if(index==index2) rotationNum++;
activating(time);
return;
}
this.#activeIndex=index;
setTimeout(()=>{
conf.success({
index,
grids:grids.map(g=>g.good)
})
},100)
},timeout)
};
activating();
}
}
讲到最后,用浏览器打开网页index.html
浏览看看,正常的话,运行效果图如下
💡小提示
试试修改传入的参数,例如
//... sm.onStart({ index: 3,//抽奖概率自己写,传入预定奖品的index success:(res)=>{ //... } });
- 1
- 2
- 3
- 4
- 5
- 6
- 7
可根据其它的需求改,
在创建对象new SlotMachines()
中修改参数goods
奖品数量,只要8个以上,可以更多,但是奖品框框数越多就变得越小了
注意另外两个参数也需要改的,参数rows
和cols
的值两个决定了能装下的奖品数量
如果看不懂,就让我认为你是萌新吧,对抽奖原理有点好奇是正常的,只需要知道,抽奖套路多,现在以真实面目展示在你的眼前,你的选择~
💡 来个打油诗 《套路》
套路千万条,
退路第一条,
一套又一套,
差点还差点。
到此结束,如阅读中有遇到什么问题,请在文章结尾评论处留言,ヾ( ̄▽ ̄)ByeBye