您好,登录后才能下订单哦!
今天小编给大家分享一下如何用JavaScript制作大转盘游戏的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
首先就是确定产品需求,仔细一看,emmm,就是正常的一个大转盘该有的东西,也没啥特殊要求,唯一需要注意的是大转盘的转盘个数需要动态变化,即用户设置多少奖品我就需要显示多少块区域。
既然要做大转盘,不外乎三个步骤:
画出大转盘
把奖励放上去
让大转盘滚起来
画出大转盘底图部分就不必多说了,最难的部分在于把一个圆动态平均分成N份,并让其在底图上正常显示。
我采用的方法是:用户选择了多少奖品(除2个奖品以外)我就在底图上生成多少个宽高为底图50%的div,目的是使每个div的右下角正好与底图的中心点重合(这里有个坑,看下去就知道了),接着计算出对应的圆心角 angle = 360 / n
,然后将其形变后以右下角为圆心旋转对应的角度拼成一个圆形。其中,形变和旋转分别采用skew与rotate进行实现。
注:
skew形变的角度为(90 - angle)deg
;
如果要给每一块加上渐变色的话,由于使用了skew形变,所以要显示从左到右的渐变的效果,就需要从原先正方形的底边变到右边,即:background: linear-gradient('45deg', color1, color2)
// 以下为N为8时,用纯JS写的一个测试demo const n = 8; // 奖品数量 const circle = document.getElementById('circle'); for(let i = 0; i < n ; i++) { let item = document.createElement('div'); item.className = `circle-item circle-item-${n}`; // n为2时,旋转原点不在右下角改为底部中点,不需要skew形变,并且宽度不是50%而是100% if(n !== 2) { item.style= `transform: rotate(${i * angle}deg) skew(${90 - angle}deg); transform-origin: bottom right; background-color: ${colorList[i % colorList.length]}; //设置了每个格子的背景色,可以不设置 ` } else { item.style= `transform: rotate(${i * angle}deg); transform-origin: bottom; background-color: ${colorList[i % colorList.length]}; ` } circle.appendChild(item); }
本以为算解决了一个难题,直到我开始测试时,发现 n == 3
时出现了奇怪的现象:
好嘛,当 n == 3
时,只设置50%的宽高显然并不能填充满整个背景图。于是更改了当 n != 2
时的样式,改为宽高的60%,并设置其初始位置往左和上各平移10%。
.circle-item { border: 1px solid; height: 60%; width: 60%; position: absolute; left: -10%; top: -10%; }
这样乍一看是实现了平均分的问题,但仔细一想还有一个问题,那便是如果加上指针,指针永远是向上的,这样看起来就怪怪的了,所以还需要将整个图像进行一个旋转,使初始指针默认指向第一块的中心位置。
旋转角度为: (180 - angle) / 2
。
把奖励放上去我想到两种方法:
1、给每个奖励生成一个与底部背景图宽高一样的正方形,然后将其对着中心点旋转对应的角度,将其一层层的放在底部背景图上,即可完成。如下图1所示,每一个正方形的大小都是与底部的背景图的宽高是一样的,只是将其进行一个旋转即可。(当时以为不好显示用户抽中的扇形的部分,就没采用这种方法,现在总结了才发现只需要将颜色填充在每个扇形中即可,不用填充在奖励背景上,如下图2所示,应该也是能实现的)
图1 每一层奖励的范围
图2 总结时想到的实现方法
2、将奖励直接放在每一个扇形区域里面,这样我就直接修改每个扇形的背景色即可。看上去很简单,但实际开始操作了就发现了两个问题:
由于每一块方格是skew形变出来的,奖励直接放上去也会产生形变,需要将形变消除;
奖励居中显示很麻烦,到现在我也没有找到可以套用的公式;
第一点解决起来较为简单,只需要将奖励进行一个反向的skew变形,旋转角度为:-(90 – (angle / 2))deg
。 第二点我到现在也没有找到可以套用的公式,是每一种给他写了一个样式居中的。(还好产品只要求2-6的奖励数量,不然可能就没有这篇文章了,如果大家有好的方法也可以教教我)
两种方法各有优点: 方法一的优点是不需要将奖励进行反向形变,怎么放上去就是怎么显示; 方法二的优点是奖励与扇形不分离,我不需要额外的添加太多的div来实现奖励正确显示。
大转盘到现在已经完成了七七八八了,现在就差最后一步,让其滚起来,点击一次后滚动到对应的位置然后停下。
采用的方法是给大转盘添加一个旋转的动画,突然想起来 transform 中有 ease-in-out 这个过渡方法,即慢-快-慢的过渡效果,正好满足我抽奖所需,于是直接采用了这种方法。
这里有个小细节,由于大转盘上本来就设置了transform的动画效果,如果不想现在的旋转动画覆盖掉之前的动画,就需要单独给动画加上一层div,放在大转盘底图的外边一层。
const circle = 8; // 旋转圈数 let circleAdd = 0; // 抽奖次数,每次抽完自增 let rotateAngle = 0; // 旋转角度 let getPrizeIndex = 0; // 抽到的奖品的index
在定义完上面的内容之后计算需要旋转的角度: rotateAngle = circle * 360 * circleAdd - angle * getPrizeIndex
,将这个rotateAngle放入需要旋转的style中即可完成旋转。
这里走了两次弯路,一次是没有加上circleAdd,然后就发现第一次大转盘会正常旋转,第二次开始就不动或者只往前滚不到360°甚至往回滚!原因是因为每一次给style赋新值的时候,由于已经有旋转的角度了,他会在你设置新的旋转角度的时候从上一个旋转角度开始执行动画。
第二次是我在写计算公式的时候,想当然的把上面的“-”写成了“+”,想的是我先旋转了circle * circleAdd
圈,然后还要滚 getPrizeIndex
个奖励就是我需要显示的奖励,然后发现指针指向的奖励与我需要选择的 getPrizeIndex
并不相符。仔细检查了才发现虽然大转盘旋转是顺时针方向的,但是奖励的读取方向应该是逆向的,所以应该是“-”而不是“+”。
以上就是“如何用JavaScript制作大转盘游戏”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。