本人主要介绍如何在微信小程序里面开发一个幸运转盘的小游戏,里面主要用到javascript
和css
语法,就可以轻松实现一个简单的幸运转盘(以6个奖品区为例)。当然,如果你有更好实现方案,欢迎在评论区留言。
前言
本次教程需要你掌握一定量javascript
和css
基础知识,并且你需要有小程序一定的开发经验,具体需要掌握知识点有:
- css 的 position、transform、transition、overflow
- javascript基本随机算法
- wxs语法
- 小程序内置动画api
效果图
![1d50e7eb788c12615e96cfcd4aca4d7d.png](https://i-blog.csdnimg.cn/blog_migrate/54cbdf394671fcd14ad63e9e8a5a824c.jpeg)
小程序
开发思路
开发思路有三部分,第一部分是用css绘制转盘背景,第二部分是利用 wxs
语法实现响应式样式 ,第三部分是小程序内置动画api实现转盘的转动以及通过js转动随机性的实现。
本人主要介绍编写思路,下面就开始我的讲解。
如何画一个三角形
一开始,要写一个基础的wxml
框架。
<view class="turntable">
<view class="wrapper">
<view class="item" >
<view class="item-inner">
<text>10分</text>
</view>
</view>
</view>
</view>
我画了两个大小相同的长方形,长和宽分别是300rpx和600rpx,利用position
css属性,让两个长方形合并在一起。
.turntable {
display: block;
width: 100%;
height: 600rpx;
}
.turntable .wrapper{
position: relative;
transform-origin: center;
width: 100%;
height: 600rpx;
}
![85f095cfe8903004227c6dc5fb40b8d4.png](https://i-blog.csdnimg.cn/blog_migrate/2c86513d645b4d090850506fdf62cdad.png)
合并之后我需要将两个长方体分离出来,把红色长方体变成半圆形,蓝色长方体顺时摆动60度,红色长方体逆时摆动30度,为什么要这样转,因为蓝色本来随红色逆时摆动30度,而一个三角形内角为60度,为了形成这60度的夹角,我需要红色摆完之后再将蓝色顺时移动60度,也就这样形成60度夹角。
.turntable .wrapper .item {
position: absolute;
left: 50%;
width: 300rpx;
height: 600rpx;
border-radius: 0px 300rpx 300rpx 0;
transform-origin: left center;
transform: rotate(-30deg);
}
.turntable .wrapper .item .item-inner {
text-align: center;
width: 300rpx;
height: 600rpx;
transform: translateX(-300rpx) rotate(60deg);
transform-origin: right center;
border-radius: 300rpx 0 0 300rpx;
font-size: 32rpx;
}
![2774b4a7ae0585dfe075d305f43281e8.png](https://i-blog.csdnimg.cn/blog_migrate/629e7281d42a7276e664766b43c07090.png)
接下来关键一步在item
处增加overflow: hidden
属性,一个三角形就出来了,并调整字体的位置。
.turntable .wrapper .item {
position: absolute;
left: 50%;
width: 300rpx;
height: 600rpx;
border-radius: 0px 300rpx 300rpx 0;
overflow: hidden;
transform-origin: left center;
}
.turntable .wrapper .item .item-inner text {
display: block;
transform-origin: center;
transform: translateY(100rpx) translateX(43rpx) rotate(-30deg);
}
![51caa65b8b1d8ef59b4ef4f1687cd4ed.png](https://i-blog.csdnimg.cn/blog_migrate/6b805927e76dc43a9e03f0f939cb18f5.png)
一个三角形画出来后,将6个同等大小的三角形并让他们可以拼接在一起组合成一个圆盘,只需各自修改三角的旋转角度即可。
.turntable .wrapper .item:nth-child(1) {
transform: rotate(-30deg);
}
.turntable .wrapper .item:nth-child(2) {
transform: rotate(-90deg);
}
.turntable .wrapper .item:nth-child(3) {
transform: rotate(-150deg);
}
.turntable .wrapper .item:nth-child(4) {
transform: rotate(-210deg);
}
.turntable .wrapper .item:nth-child(5) {
transform: rotate(-270deg);
}
.turntable .wrapper .item:nth-child(6) {
transform: rotate(-330deg);
}
实现响应式样式
为了更好的适应不同业务需求,我把转盘的样式变成响应式,就可以轻松根据用外部传入的 prize 数据的长度来设置不同的样式,我把这一步的判断,放在wxs
模块那里。
<wxs module="computed">
var rotate = function (index, length) {
var inital = - (360 / length / 2)
var averageRotate = 360 / length
var deg = inital - averageRotate * index
return 'transform: rotate(' + deg + 'deg);'
}
var inner = function (length) {
var averageRotate = 360 / length
return 'transform: translateX(-300rpx) rotate(' + averageRotate + 'deg);'
}
var text = function (length) {
var distance = 0
var rotate = 0
switch (length) {
case 6:
distance = 43
rotate = 30
break
case 8:
distance = 72
rotate = 30
break
case 4:
distance = -20
rotate = 40
break
}
return 'transform: translateY(100rpx) translateX(' + distance + 'rpx) rotate(-45deg);'
}
module.exports = {
rotate: rotate,
inner: inner,
text: text
}
</wxs>
动画系统和中奖系统
通过设定好的中奖率,以一个圆为360度来计算,得出一个0-360的中奖范围,将随机得来的数判断属于哪个区间值,用区间值reward
来决定圆盘所需转动的角度。思路大概就是这样,下面开始讲解主要的思路。
圆盘要转的角度 = reward * 一个圆分成6块的平均值 + 3 * 360
首先要设置好6个奖品区的中奖率winning
,该中奖率要相加起来为1,把初始化的数据组合成一个6位数的数组从组件外传入进组件内。
prize: [{
'name': '1分',
'winnning': 0.2,
'count': 1
},
{
'name': '谢谢参与',
'winnning': 0.5,
'count': 0
}, {
'name': '5分',
'winnning': 0.05,
'count': 5
}, {
'name': '7分',
'winnning': 0.05,
'count': 7
},
{
'name': '3分',
'winnning': 0.1,
'count': 3
},
{
'name': '4分',
'winnning': 0.1,
'count': 4
}
],
以一个圆为360度来计算出0-360的中奖取值范围。
getRange(winning) {
let temp = []
winning.forEach((item, index) => {
if (index === 0) {
temp.push(item['winnning'] * 360)
} else {
temp.push(parseInt(temp.slice(-1)) + item['winnning'] * 360)
}
})
return temp
},
生成一个随机整数,当然这数要在0-360,不然超出360或小于0是没有意义的。
获得随机数之后,判断在哪个奖品范围内并把在对应的区间值赋予响应数reward
内。
for (let i in winningRange) {
let currentwinning = winningRange[i] // 当前取值
if (random < currentwinning) {
this.setData({
reward: i
})
break
} else {
if (i == 0) {
continue
}
if (random >= winningRange[i - 1] && random <= currentwinning) {
this.setData({
reward: i
})
break
}
}
}
把点击开始的主函数放在onPoint()
内,函数开始时需判断是否仍有抽奖机会以及防止在执行动画又点击函数执行动画,经过计算得来所需的角度通过微信小程序的动画apianimation
来让圆盘实现转动,动画结束后把中奖信息通过自定义组件触发事件来让组件外监听到。
onPoint() {
// 平均值
const averageRotate = 360 / this.properties.prize.length
// 是否有抽奖机会
if (this.properties.chance === 0) {
this.triggerEvent('none')
return
}
// 防止转动时点击开始按钮
if (!this.data.onRotation) {
this.setData({
onRotation: true
})
this.getReward()
let deg = this.data.reward * averageRotate + 3 * 360 // 至少3圈以上
this.animate('.wrapper', [{
rotate: 0,
ease: 'ease-in-out'
},
{
rotate: deg,
ease: 'ease-in-out'
}
], 5000, function () {
this.setData({
onRotation: false
})
// 发送自己的抽奖信息
this.triggerEvent('onResult', this.properties.prize[this.data.reward])
}.bind(this))
}
},
最后别忘了在每次执行动画前,都要先执行动画重置动作,才能保证动画下次转到正确的角度。当然我把其放在一个函数里面,以便组件外也可以使用该函数。
onClear(){
this.clearAnimation('.wrapper')
}
最后
整个思路就这些,怎么样,是不是很简单呢?实现关键一步是绘制圆盘,只要这一步搞好了,其他就会简单很多,因为动画实现那部分,微信小程序已经帮我们全部弄好了。最后,如果有更好的方法,欢迎在评论讨论一下。
特别要说一下,该转盘项目放在我微信小程序实例中运行,大家可以扫码进去小程序,在主页最下面就能看到入口端口。
转盘代码仓:
turntablegithub.com项目演示
你可登陆小程序主页面后,拉到主页面最下面,找到“参与抽奖”,即可进入幸运转盘的小游戏。
![a8873a4a722ef78915357c6591a8bfb7.png](https://i-blog.csdnimg.cn/blog_migrate/9561b750496ee951494d3174b9c2d682.png)