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. 总结
- 使用现有的算法库,减少了我的工作量;
- 在不考虑异步中奖的时候,我觉得这个实现是比较便捷的方法,当然如果需要异步中奖结果,就需要多个动画配合实现,这个功能准备将这个算法库移植到微信小程序后再实现;
- 同一个需求,实现的方法很多,找到最适合自己的,多关注大佬的博客,学习,感觉收获满满!!!