vue简单实现转盘抽奖

 4621

这篇文章主要为大家详细介绍了vue简单实现转盘抽奖,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了vue简单实现转盘抽奖的具体代码,供大家参考,具体内容如下

1.0 思路整理

转盘抽奖很常见,之前也没写过,现在有空来写写,分析如下:

1.1 转盘旋转 ----- 可以用 transform 的 rotate 来解决

1.2 旋转动画 ----- transition 过渡来处理

1.3 停留目标位置及中奖提示 ? ------ 通过控制旋转角度控制停留位置,中奖提示,考虑添加回调

1.1 开始行动

上面的思考,我们知道了大概要实现的步骤,首先我们搞张图片


vue简单实现转盘抽奖


这个圆盘有 10 份,每一份 360/10 = 36deg,假设要停留在第二个---->20金币,顺时针(含初始位置并计为1),即 共需要旋转 (2 - 1)* 36 = 36,这样,我们可以得出,停留位置需要旋转的角度 = (target - 1)*36。


1.2 中奖回调

上面的步骤,我们知道了如何控制到目标位置,那接下来就是事件通知,起初想的是,固定转动时间,然后开启定时器计时,很显然不靠谱,有没有什么可以在动画结束后就通知呢?transitionend,我找到了这个事件,可以监听元素动画结束事件,只不过有些兼容 这个好办

  1. /**
  2. 动画结束事件兼容
  3. **/
  4. whichTransitionEvent(){
  5.     let el = document.createElement('span'),
  6.     transitions = {
  7.         'transition':'transitionend',
  8.         'OTransition':'oTransitionEnd',
  9.         'MozTransition':'transitionend',
  10.         'WebkitTransition':'webkitTransitionEnd'
  11.     };
  12.     for(let t in transitions){
  13.         if( el.style[t] !== undefined ){
  14.             return transitions[t];
  15.         }
  16.     }
  17.     el = null;
  18. }

2.0 完整示例

控制转动位置和事件通知都找到方法了,接下来开干!

栗子:


vue简单实现转盘抽奖


完整代码

  1. <template>
  2.     <div>
  3.         <h3>转盘抽奖</h3>
  4.         <div >
  5.             <img ref="rotImg" src="../assets/zhuan.png" alt="">
  6.             <div>
  7.                 <div ></div>
  8.             </div>
  9.         </div>
  10.         <button @click="toDraw" >点击抽奖</button>
  11.     </div>
  12. </template>
  13.  
  14. <script>
  15. export default {
  16.     name:'rotaryDraw',
  17.     data() {
  18.         return {
  19.             rotate: 0,
  20.             resetRotate: 0,
  21.             hitId: 1,// 1-10
  22.             drawStatus: false
  23.         }
  24.     },
  25.     async mounted() {
  26.         await this.$nextTick();
  27.         let evenTransition = this.whichTransitionEvent();
  28.         let img = this.$refs.rotImg;
  29.         let that = this;
  30.         const hitAre = [ '30M流量包','20金币','20M流量包','10M流量包','5金币',
  31.             '谢谢参与','10金币','50M流量包','2金币','100M流量包'
  32.         ];
  33.         // 监听 动画结束 
  34.         img.addEventListener(evenTransition,tranHand,false);
  35.         function tranHand() {
  36.             // 复位
  37.             that.resetRotate = that.rotate > 360 ? that.rotate % 360 : 0;
  38.             img.style.transition = "none 0s ease 0s";
  39.             img.style.transform = `rotate(${that.resetRotate}deg)`; 
  40.             alert(`抽奖结果【 ${hitAre[that.hitId - 1]} 】`);
  41.             that.drawStatus = false
  42.         }
  43.     },
  44.     methods: {
  45.         start() {
  46.             this.$refs.rotImg.style.transition = "all 3s ease 0s";
  47.             this.$refs.rotImg.style.transform = `rotate(${this.rotate}deg)`;
  48.         },
  49.         toDraw() {
  50.             if(this.drawStatus){
  51.                 console.log('正在抽奖中');
  52.                 return
  53.             }
  54.             // 标记状态
  55.             this.drawStatus = true
  56.             /**
  57.              * 圆盘共 10 份 每份 36度, 停位置(id)度数 (id - 1)*36 
  58.              * 基数 3圈 360*4
  59.              * this.rotate 当前角度
  60.              * **/ 
  61.             let reset = 360 * 4;
  62.             let idx = this.getRandomInt(1,11);
  63.             // 设置命中
  64.             this.hitId = idx;
  65.             // 需要多转角度
  66.             let addRotate = this.resetRotate > 0 ? 360 - this.resetRotate : 0;
  67.             // 总共角度
  68.             let allRotate = this.rotate + (idx - 1) * 36 + reset + addRotate;
  69.             // 角度限制
  70.             this.rotate = this.setRotate(allRotate);
  71.             this.start()
  72.         },
  73.         // 递归计算角度 不超过 360*6
  74.         setRotate(deg) {
  75.             let rest = deg - 360;
  76.             return rest > 360*6 ? this.setRotate(rest) : deg;
  77.         },
  78.         getRandomInt(min, max) {
  79.             // 向上收
  80.             min = Math.ceil(min);
  81.             // 向下收
  82.             max = Math.floor(max);
  83.             return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值
  84.         },
  85.         // 动画兼容
  86.         whichTransitionEvent(){
  87.             let el = document.createElement('span'),
  88.             transitions = {
  89.                 'transition':'transitionend',
  90.                 'OTransition':'oTransitionEnd',
  91.                 'MozTransition':'transitionend',
  92.                 'WebkitTransition':'webkitTransitionEnd'
  93.             };
  94.             for(let t in transitions){
  95.                 if( el.style[t] !== undefined ){
  96.                     return transitions[t];
  97.                 }
  98.             }
  99.             el = null;
  100.         }
  101.     }
  102. }
  103. </script>
  104.  
  105. <style >
  106. .img_rotate{
  107.     transform: rotate(0deg);
  108. }
  109. .round_box{
  110.     width: 100%;
  111.     max-width: 375px;
  112.     position: relative;
  113.     overflow: hidden;
  114. }
  115. img{
  116.     width: 100%;
  117. }
  118. .center{
  119.     position: absolute;
  120.     top: 50%;
  121.     left: 50%;
  122.     transform: translate(-50%,-50%);
  123. }
  124. .pointer{
  125.     width: 5px;
  126.     height: 90px;
  127.     background-color: #f40;
  128.     position: absolute;
  129.     top: -90px;
  130. }
  131. .pointer::before{
  132.     content:'';
  133.     width: 0;
  134.     height: 0;
  135.     border-top: 15px solid transparent;
  136.     border-right: 15px solid transparent;
  137.     border-bottom: 15px solid #f40;
  138.     border-left: 15px solid transparent;
  139.     position: absolute;
  140.     top: -20px;
  141.     left: 50%;
  142.     transform: translateX(-50%);
  143. }
  144. </style>

3.0 tips

总体来说有几个点需要注意

1、动画开始前上锁

2、动画结束后通知,状态复位

  1. /**
  2. 比如:
  3. 基数3圈 reset 360*3
  4. 停留位置 第二个 (2 - 1)* 36 = 36
  5. 总共角度 360*3 + 36
  6. 动画停止后,因为还要继续旋转,所以不可能把角度一直增加,因此需要复位 
  7. 360*3 + 36 其实可以考虑 就转了 36度,然后再增加需要转的角度
  8. **/

3、继续旋转,因为我们计算是以 30M流量 为初始值的,所以在此旋转 仍然需要以 30M为起点,此时假设 现在停留位置是 300度,也就是说 再转 60度,也就回到了初始位置,本人也是按照这个思路进行复位的。


本文网址:https://www.zztuku.com/index.php/detail-8718.html
站长图库 - vue简单实现转盘抽奖
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐