【JavaScript】制作一个老虎机抽奖页面

开发H5项目,有时会遇到一个需求,需要制作仿制老虎机游戏抽奖的网页,这个实现步骤,如果拿现成的改来做是容易的,但是想着全靠自己做是不容易的,接下来开始讲,想不想自己做,有把握学到吗

1. 设计网页


首先创建一个网页文件,例如index.html,制作老虎机游戏抽奖页面,源代码如下,通过修改样式<style>里设置好背景色,还有组件的位置,再加一个抽奖按钮,写好大概逻辑,还有需要调用的一些方法

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>老虎机 Slot Machines</title>
		<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>

2. 编写脚本

接着,写一个加载脚本的处理逻辑,代码如下,使用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);
		}
	})
}

3. 编写模块

接下来,看上面有引用的一个模块文件slot_machines.js,没有的就把它新建好,在一个模块中去实现上面未实现的调用方法,代码如下

export default class SlotMachines{
	
	constructor(object,window){
		// 这里做一些初始化的工作...
	}
	
	onStart(conf={}){
		// 这里做抽奖的处理逻辑和动画...
	}
}

4. 实现方法

接下来,写方法的实现细节要复杂得多,如果看着比较吃力,就先收藏好,以后有时间慢慢摸索,边学边做

1. 绘制老虎机

在构造方法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={}){
		//这里做抽奖的处理逻辑和动画...
	}
}

2. 开始抽奖

实现开始抽奖方法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();
	}
}

4.运行效果

讲到最后,用浏览器打开网页index.html浏览看看,正常的话,运行效果图如下
请添加图片描述

💡小提示

试试修改传入的参数,例如

//...
sm.onStart({
	index: 3,//抽奖概率自己写,传入预定奖品的index
	success:(res)=>{
 		//...
	}
});

可根据其它的需求改,
在创建对象new SlotMachines()中修改参数goods奖品数量,只要8个以上,可以更多,但是奖品框框数越多就变得越小了
注意另外两个参数也需要改的,参数rowscols的值两个决定了能装下的奖品数量

如果看不懂,就让我认为你是萌新吧,对抽奖原理有点好奇是正常的,只需要知道,抽奖套路多,现在以真实面目展示在你的眼前,你的选择~

💡 来个打油诗 《套路》
套路千万条,
退路第一条,
一套又一套,
差点还差点。

到此结束,如阅读中有遇到什么问题,请在文章结尾评论处留言,ヾ( ̄▽ ̄)ByeBye
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TA远方

谢谢!收到你的爱╮(╯▽╰)╭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值