1. 实现效果
2. 需求分析
- 它和正常的转盘抽奖不一样,一般实现都是指针形式的,转盘转动,最后指针停留在奖品的随机位置;
- 通过上边图发现奖品必须刚好停留在奖品的位置,因为不是指针,所以不能最后落到随机位置。
3. 常见转盘抽奖实现
常见九宫格抽奖和转盘抽奖组件实现!!!
4. 使用库
- 张鑫旭大佬实现的动画函数算法库
- 如何使用Tween.js各类原生动画运动缓动算法,使用文档
5. 引入 Tween.js 算法库
<script src="./js/tween.js"></script>
<script src="./js/animation.js"></script>
6. HTML 布局
- 转盘图片 game_luck.png;
- 指针图片 game_check.png;
- 开始按钮 game_btn.png。
<div class="rui-game-luck-content">
<img src="./images/game_luck.png"
:style="`transform: translate(-50%, -50%) rotate(${angleNumber}deg)`"
:data-id="angleNumber"
id="turntable"
class="rui-game-luck-img" alt="">
<img src="./images/game_check.png" style="z-index: 10;" class="rui-game-luck-img" alt="">
<img src="./images/game_btn.png" @click="drawLuck" class="rui-game-luck-btn" alt="">
</div>
7. CSS 实现
.rui-game-luck-content{
width: 5.38rem;
height: 5.38rem;
position: relative;
margin: 1.55rem auto 0.35rem;
}
.rui-game-luck-img{
width: 5.38rem;
height: 5.38rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.rui-game-luck-btn{
width: 2.26rem;
height: 2.26rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12;
}
8. 点击旋转动画实现
- 申明一个 Lock 锁,用于防止抽奖时的重复点击;
- 抽奖的各个变量申明;
- 抽奖次数已用完判断;
- 判断锁是否生效;
- 生成0到5之间的随机整数;
- 计算最后的角度;
- 转盘旋转动画;
- 抽奖次数减少;
- 显示遮罩层中奖奖品;
- 记录上一次转动最终角度。
const lock = new Lock();
var app = new Vue({
el: "#app",
data: {
show: false, // 遮罩层
luckNumber: 0, // 中奖位置
luckList: ['成长快乐','笑口常开','健康活泼','成长快乐','笑口常开','健康活泼'], // 奖品列表
angleNumber: 0, // 转盘旋转角度
drawNumber: 3, // 抽奖次数
recordPrevAngle: 0, // 上一次转动最终角度
drawOverMask: false, // 抽奖次数已用完遮罩层
},
methods: {
// 再抽一次
drawAgainLuck(){
this.show = false;
this.drawLuck();
},
// 抽奖
drawLuck(){
// 抽奖次数已用完
if(this.drawNumber <= 0){
this.drawOverMask = true;
return false;
}
// 判断锁是否生效
if(lock.isLocked){
return false;
}
// 获取锁
lock.acquire();
let _this = this;
let prevLuckAngle = this.luckNumber * 60;
// 生成0到5之间的随机整数
let randomNum = Math.floor(Math.random() * this.luckList.length);
this.luckNumber = randomNum;
// 计算最后的角度
let endAngle = 360 * 20 + _this.luckNumber * 60 - prevLuckAngle;
// 转盘旋转动画
Math.animation(_this.recordPrevAngle, _this.recordPrevAngle + endAngle, 5000, 'Cubic.easeInOut',function(value, isEnding) {
_this.angleNumber = value;
if(isEnding){
lock.release(); // 释放锁
// 抽奖次数减少
_this.drawNumber--;
// 显示遮罩层中奖奖品
_this.show = true;
// 记录上一次转动最终角度
_this.recordPrevAngle += endAngle;
console.log(_this.luckList[_this.luckNumber])
}
})
}
}
});
9. 最终效果
10. 总结
- 使用现有的算法库,减少了我的工作量;
- 在不考虑异步中奖的时候,我觉得这个实现是比较便捷的方法,当然如果需要异步中奖结果,就需要多个动画配合实现,这个功能准备将这个算法库移植到微信小程序后再实现;
- 同一个需求,实现的方法很多,找到最适合自己的,多关注大佬的博客,学习,感觉收获满满!!!