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













![[算法面试]_01_L1和L2正则化,为什么L1正则化更容易导致稀疏?](https://img-blog.csdnimg.cn/direct/4825200b73e34327a73f0990667fab7e.png)




