zoukankan      html  css  js  c++  java
  • vue 中实现大转盘抽奖

    想要开发一个,可进行配置奖品的大转盘抽奖活动:如下图:

    要求: 转盘底图可配置,相对应的奖品也能够配置

        

    开发思路:

    1. 可以把转盘开发成一个组件,所有参数皆是可配置的,做成组件具有公用型
    2. 通过 transform的rotate旋转 以及 transition过渡来实现动画
    3. 确定旋转实现的原理,不想能像表盘那样指针转,应该是指针不动,表盘旋转,用户体验性更好 

    具体实现步骤:

      1.dom加载完成后,在mounted钩子中写一个transition平移动画

      

       //渲染完了
        mounted() {
          this.oTurntable = document.querySelector('#turnUl');
          // 过度中属性用时5s
          this.oTurntable.style.webkitTransition = 'transform ' + this.time / 1000 + 's ease';
        },

      2.先根据奖品列表数量来计算每个奖品对应的角度,指针一般是定位到该中奖奖品的中心位置,这个要考虑到

    autoRotate(arr) {
          if (arr.length) {
              let len = arr.length;
              let base = 360 / len;
              arr.forEach((item, index) => {
                // 指的是某个奖品区域的中间 : base/2
                item.angle = 360 - (base / 2 + index * base);
              });
          }
          return arr;
    },

      3.点击按钮时请求接口,拿到中奖奖品进行旋转到之前计算好的该奖品的角度,可以写在定时器当中,完成后即清除定时器

          // 点击开始,请求接口抽奖
          startPlay(){
            const a = {
              prize: "50元和包券",
              id: 4
            }
            this.startBtn(a)
          },
          // 开始转动,通过奖项级别进行匹配:id 
          startBtn(val) {
            const self = this
            self.activeObj.prizeData.forEach((i,d)=>{
              if(i.id == val.id){
                self.pIndex = d
              }
            })
            // 拿到相应的角度调旋转接口
            self.startrotate(self.activeObj.prizeData[self.pIndex].angle, () => {
              self.fulfillHandle(self.activeObj.prizeData[self.pIndex].prize);
            });
          },
    
          //开始旋转 angle角度  complete回调成功函数
          startrotate(angle, complete) {
            // 相应的角度 + 满圈 只是在原角度多转了几圈 360 * 6
            let rotate = 2160 * (this.rotNum + 1) + angle;
            this.oTurntable.style.webkitTransform = 'rotate(' + rotate + 'deg)';
            clearTimeout(this.timer);
            // 设置5秒后停止旋转,处理接口返回的数据
            this.timer = setTimeout(() => {
              complete();
              this.rotNum++;
            }, this.time);
          },
          //得奖后的处理
          fulfillHandle(prizeName) {
            this.$emit('result',prizeName)
          },

      4.抽奖旋转结束后再去处理后续操作,写在startrotate 这个函数中,通过吧结束处理的函数当做参数进行回调

    下面是完整代码:

    html:

    <template>
      <div id="turnBox">
        <ul id="turnUl" :style="{ backgroundImage : 'url(' + activeObj.turntableBgc + ')'}">
          <li
            v-for="(item,index) in activeObj.prizeData"
            :key="index"
            :style="{webkitTransform: 'rotate(' + -item.angle + 'deg)'}"
          >
          </li>
        </ul>
        <img :src="activeObj.turntablebtn" alt=""  @click="startPlay" class="turnBtn">
      </div>
    </template>

    js:

    <script>
      export default {
        props: {
          activeObj: {
            type: Object,
            default: null
          },
        },
        data(){
          return {
            pIndex: 0, // 中奖物品的下标
            rotNum:  0, // 旋转圈数基数
            time: 5000, // 旋转时间
            timer: null, // 定时器
            oTurntable: '', // 旋转圆盘背景图
            type: 0, // 0 图片 1 汉字
          }
        },   
        created() {
          this.activeObj.prizeData = this.autoRotate(this.activeObj.prizeData)
          console.log(this.activeObj.prizeData);
        },
        //渲染完了
        mounted() {
          this.oTurntable = document.querySelector('#turnUl');
          // 过度中属性用时5s
          this.oTurntable.style.webkitTransition = 'transform ' + this.time / 1000 + 's ease';
        },
        methods:{
          //自动生成角度添加到数组上
          autoRotate(arr) {
            if (arr.length) {
              let len = arr.length;
              let base = 360 / len;
              arr.forEach((item, index) => {
                // 指的是某个奖品区域的中间 : base/2
                item.angle = 360 - (base / 2 + index * base);
              });
            }
            return arr;
          },
          // 点击开始,请求接口抽奖
          async startPlay(){
            const a = {
              prize: "50元和包券",
              id: 4
            }
            this.startBtn(a)
          },
          // 开始转动,通过奖项级别进行匹配:id 
          async startBtn(val) {
            const self = this
            self.activeObj.prizeData.forEach((i,d)=>{
              if(i.id == val.id){
                self.pIndex = d
              }
            })
            // 拿到相应的角度调旋转接口
            self.startrotate(self.activeObj.prizeData[self.pIndex].angle, () => {
              self.fulfillHandle(self.activeObj.prizeData[self.pIndex].prize);
            });
          },
    
          //开始旋转 angle角度  complete回调成功函数
          startrotate(angle, complete) {
            // 相应的角度 + 满圈 只是在原角度多转了几圈 360 * 6
            let rotate = 2160 * (this.rotNum + 1) + angle;
            this.oTurntable.style.webkitTransform = 'rotate(' + rotate + 'deg)';
            clearTimeout(this.timer);
            // 设置5秒后停止旋转,处理接口返回的数据
            this.timer = setTimeout(() => {
              complete();
              this.rotNum++;
            }, this.time);
          },
          //得奖后的处理
          fulfillHandle(prizeName) {
            this.$emit('result',prizeName)
          },
          
          //自动换行
          autoWrap(str) {
            if (str.length > 5 && str.length <= 10) {
              str = str.substring(0, 5) + '<br/>' + str.substring(5, str.length);
            } else if (str.length > 10) {
              str = str.substring(0, 5) + '<br/>' + str.substring(5, 9) + '...';
            }
            return str;
          }
        }
      }
    </script>

    css:

    <style lang="less" scoped>
      #turnBox {
         545px;
        height: 544px;
        position: relative;
        overflow: hidden;
        margin: 0px auto;
        margin-top: 30px;
        background-position: center center;
        .turnBtn {
          position: absolute;
           1.3rem;
          left: 50%;
          top: 50%;
          transform: translateX(-50%) translateY(-59%);
          overflow: hidden;
          background-repeat: no-repeat;
          background-size: 100% auto;
          z-index: 3;
        }
        ul {
          position: absolute;
           100%;
          height: 100%;
          z-index: 1;
          background-repeat: no-repeat;
          background-size: 100% auto;
          li {
            position: absolute;
            box-sizing: border-box;
            // padding-top: 0.5rem;
            color: #7e250d;
            font-size: 0.3rem;
            top: 0pc;
            left: 0px;
             100%;
            height: 100%;
            line-height: 20px;
            transform-origin: 50% 50%;
            img {
              position: absolute;
              top: 0.3rem;
              left: 50%;
              transform: translateX(-50%);
               20%;
            }
          }
        }
      }
    
    </style>
  • 相关阅读:
    vsftp部署和优化错误
    部署和调优 1.6 vsftp部署和优化-2
    部署和调优 1.5 vsftp部署和优化-1
    部署和调优 1.3 pureftp部署和优化-2
    Linux一些常用软件的源码安装
    SecureCrt 利用公匙登录L机取消密码登录。
    利用任务自动上传备份。
    Mysql Too Many Connections问题解决
    Linux ---pptpd部署
    Sed简单入门实例
  • 原文地址:https://www.cnblogs.com/huangaiya/p/12762473.html
Copyright © 2011-2022 走看看