抽奖转盘,原生js,canvas绘制

原生js写的抽奖转盘,可以控制指定商品的抽取概率
样式高度自适应,不过最多只能分十份,只需要改变productInformation里面的数量就行!!!

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
	<title></title>
	<style type="text/css">
		*{
			margin: 0;
			padding: 0;
		}
		#canvas{
			border-radius: 50%;
			border: green 1px solid;
		}
	</style>
</head>
<body>
	<canvas id="canvas"></canvas>
	<div>
		<button onclick="singleDraw()">单抽</button>
		<button onclick="multiDraw()">多连抽</button>
	</div>
	<script type="text/javascript">

		//圆盘插入的东西,图片,背景颜色,内容,概率范围
		var productInformation = [
			{imgUrl:"img/mix8.png",bg:"pink",content:"小米翡翠绿",probabilitySmall:0,probabilityMax:0.05},
			{imgUrl:"img/mix9.png",bg:"black",content:"cc9猛男配色",probabilitySmall:0.05,probabilityMax:0.7},
			{imgUrl:"img/mix1.png",bg:"green",content:"天空之境",probabilitySmall:0.7,probabilityMax:0.78},
			{imgUrl:"img/mix4.png",bg:"red",content:"红米k20",probabilitySmall:0.78,probabilityMax:0.85},
			{imgUrl:"img/mix5.png",bg:"skyblue",content:"小米10",probabilitySmall:0.85,probabilityMax:0.93},
			{imgUrl:"img/mix2.png",bg:"orange",content:"mix alpho",probabilitySmall:0.93,probabilityMax:1}
		]
		var produLength = productInformation.length;

		var multiDrawNum = 10; //多连抽的次数
		var fontS = "14px Arial"; //文字大小,字体
		var fontC = "white"; //文字颜色
		var width = 300;  //canvas宽
		var height = 300; //canvas高
		var imgW = 30;   //图片宽
		var imgH = 30;	  //图片高
		var imgUrl = 'img/tv1.png'; //背景图片路径
		var time = 700; //多连抽返回抽取结果的间隔时间

		//用颜色做背景的转盘,各个份数的扇形偏角 10份及以内,通过这来让其自适应
		var cornerSet = [
			{nn:''},
			{nn:Math.PI/6},
			{nn:0.26*Math.PI},
			{nn:0.31*Math.PI},
			{nn:''},
			{nn:0.36*Math.PI},
			{nn:0.37*Math.PI},
			{nn:0.38*Math.PI},
			{nn:0.4*Math.PI}
			]; 
		
		//开始
		var canvas = document.getElementById('canvas');
		var ctx = canvas.getContext('2d');
		var prizeList = [];   //商品在转盘上的位置,由于每张图片加载完成的时间不同导致商品对应的位置也不同
		canvas.width = width;  
		canvas.height = height;
		//canvas.style.backgroundImage = "url("+imgUrl+")"; //插入背景图
		var angle = 2*Math.PI; //圆
		var deflection = angle/produLength; //根据productInformation的数量来每个扇形的弧度
		
		ctx.translate(width/2,height/2);  //图片旋转的中心点
		for(let i=0;i<produLength;i++){
			//绘制扇形圆
			ctx.save();
			ctx.beginPath(); //开始,每次绘制以这为起始
			ctx.moveTo(0,0);  //起始的位置
			
			//从偏角集合里拿取其对应的份数的偏角,从而达到自适应
			ctx.arc(0,0,width/2,i*deflection-cornerSet[produLength-2].nn,(i+1)*deflection-cornerSet[produLength-2].nn);
			/*ctx.rotate(deflection);	
			ctx.arc(0,0,width/2,0,deflection);*/

			ctx.fillStyle = productInformation[i].bg; //填充颜色
			ctx.fill(); //填充

			//插入图片
			(function(i){
				var img = new Image();
				img.src = productInformation[i].imgUrl;	
				img.onload = () =>{
					prizeList.push(i); //将图片对应的位置放进数组里
					ctx.rotate(deflection); //图片旋转的角度

					ctx.drawImage(img,-imgW/2,-((width/2)*7/8),imgW,imgH);//插入图片

					//先绘完图再绘文字,不然文字会被背景色和图片遮住
					//先绘完图再绘文字,不然文字会被背景色和图片遮住
					ctx.font=fontS; //文字大小,字体
					ctx.fillStyle = fontC; //文字颜色
					var fontW = ctx.measureText(productInformation[i].content).width; //获取当前字体宽度
					ctx.fillText(productInformation[i].content,-fontW/2,-((width/2)*6/10)); //文字内容,坐标
					
				}
			}(i))		
		}

		//旋转
		var isSpin = true;
		var aa = 2880;//一次转多少圈
		
		//单抽
		function singleDraw(){	
			if(isSpin){

				isSpin = false; 
				var probability = Math.random()
				var multiple;
				for(let i=0;i<produLength;i++){
					//通过probability这随机数来匹配productInformation里的概率范围,在谁区间里就让multiple变为值定的数来抽取该产品
					if(productInformation[i].probabilitySmall < probability && probability <= productInformation[i].probabilityMax){
						//由于图片加载时长不同,其在转盘的位置也不固定,所以通过prizeList来知道该产品的正确位置
						for(let j=0;j<prizeList.length;j++){
							if(prizeList[j] == i){
								if(j < (produLength-1)){
									multiple = produLength - j -1;
								}else{
									multiple = produLength;
								}
							}
						}
					}
				}			
				console.log(aa);
				console.log(aa + (multiple*360/produLength));
				//通过multiple来决定抽取到哪一个
				canvas.style.transform = 'rotate(' + (aa + (multiple*360/produLength)) +'deg)';
				canvas.style.transition = 'all 2.5s ease';//转盘过度时间
				
				aa += 2880; //让转盘能继续转
				console.log(aa);
				setTimeout(()=>{
				//由于图片加载完的时间顺序不固定,其在的位置也不固定,所以要这样换算才能拿到指定的东西
				//prizeList是图片加载完后,轮盘每个位置真正对应的东西
					if(multiple == produLength){
						var num = prizeList[produLength-1]; 
						console.log("奖品是:"+productInformation[num].content);
					}else{
						var ll = produLength - multiple - 1;
						var num = prizeList[ll];
						console.log("奖品是:"+productInformation[num].content);
					}
					isSpin = true;
				},2700)

			}
		}
		
		//多连抽
		function multiDraw(num){
			if(isSpin){
				isSpin = false;
				var probability;
				var prizeCollection = [];//抽取结果集合
				var lis = 0; 
				console.log('多连抽aa:'+aa);
				console.log(aa+(2880*multiDrawNum));
				if(num == 1){
					canvas.style.transform = 'rotate(' + aa +'deg)';
					canvas.style.transition = 'all 2.5s ease-out';
				}else{
					canvas.style.transform = 'rotate(' + aa*multiDrawNum +'deg)';
					canvas.style.transition = 'all '+ (time*multiDrawNum+1500) +'ms ease-out';//转盘过度时间
				}
				
				aa += aa*multiDrawNum;
				console.log('多连抽aa:'+aa);
				for(let i=0;i<multiDrawNum;i++){
					probability = Math.random(); //根据multiDrawNum抽取次数来创建多个随机数
					//查找,找到相应的就把结果返回出去且不再继续查找
					let data = productInformation.find(res =>{
						if(res.probabilitySmall < probability && probability <= res.probabilityMax){return res}
					})
					prizeCollection.push(data.content);//将结果放进该数组
				}

				//根据num传的值是否为1来决定其返回结果的方式
				if(num == 1){
					//直接一次性把抽取结果返回
					console.log(prizeCollection);
					isSpin = true;
				}else{
					//逐个返回抽取结果
					const clock = setInterval(e =>{
						console.log(prizeCollection[lis]);
						lis +=1;
						if(lis >= prizeCollection.length){
							clearInterval(clock);
							isSpin = true;
						}
					},time)
				}
				
			}
		}
		
		
	</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值