H5九宫格抽奖,亲测可用

前提准备:scss 和 px2rem-loader  具体可以查看

一、新建抽奖组件 Lottery.vue

 1、新components建文件夹lottery,包含src文件夹和index.js,src下面新建抽奖组件 Lottery.vue,lottery.scss

 index.js

/**
 * {Array} prizesList : 抽奖图片数组 , 默认 []
 * {Object} lotteryBtn : 抽奖按钮图片 , 默认 {img : ""}
 * {Number} prize : 中奖位置 , 默认 0
 * {Number} speed : 速度 , 默认 100
 * {Number} cycle : 转动次数 , 默认 20
 * {Function} beforeLottery : 抽奖前处理函数 , 可用于发送请求获取结果 , 必须定义
 * beforeLottery 需要引入两个参数 resolve 成功之后调用 , reject失败之后调用,可在reject里面写回调函数
 * {Function} afterLottery : 抽奖结束回调函数 , 用于处理结果
*/

export { default } from './src/Lottery.vue'

 Lottery.vue

<template>
  <div class="iv-lottery">
    <ul>
      <li class="row">
        <div :class="['col-4' , {active : activeClass[index]}]"
             v-for="(item,index) in lis1"
             :key="index" class="prize">
          <img :src="item.imgUrl">
          <p class="prizeName">{{item.prizeName}}</p>
        </div>
      </li>
      <li class="row">
        <div :class="['col-4' , {active : activeClass[7]}]" class="prize">
          <img :src="lis2Img.imgUrl">
          <p class="prizeName">{{lis2Img.prizeName}}</p>
        </div>
        <div class="col-4"
             @click="startLottery">
            <div class="luck-btn">
              <p class="luck-btn-txt">抽奖</p>
            </div>
        </div>
        <div :class="['col-4' , {active : activeClass[3]}]" class="prize">
          <img :src="lis3Img.imgUrl">
          <p class="prizeName">{{lis3Img.prizeName}}</p>
        </div>
      </li>
      <li class="row">
        <div :class="['col-4' , {active : activeClass[6-index]}]"
             v-for="(item,index) in lis4"
             :key="index" class="prize">
          <img :src="item.imgUrl">
          <p class="prizeName">{{item.prizeName}}</p>
        </div>
      </li>
    </ul>
  </div>
</template>

<script type="text/javascript">
import './lottery.scss'
export default {
  name: 'Lottery',
  data () {
    return {
      activeClass: [false, false, false, false, false, false, false, false],
      index: -1,
      count: 8,
      timer: null,
      times: 0,
      speedData: 100,
      afterLotteryHandler: null
    }
  },
  props: {
    prizesList: {
      type: Array,
      default () {
        return []
      }
    },
    lotteryBtn: {
      type: Object,
      default () {}
    },

    beforeLottery: {
      type: Function,
      default () { throw new Error('you must define beforeLottery before draw a lottery ') }
    },

    afterLottery: {
      type: Function,
      // eslint-disable-next-line
      default () { console.warn('you can use afterLottery after rolling'); }
    },

    prize: {
      type: Number,
      default: 0
    },
    speed: {
      type: Number,
      default: 100
    },
    cycle: {
      type: Number,
      default: 20
    }
  },
  computed: {
    lis1 () {
      let list = []
      this.prizesList.forEach(item => {
        if ([1, 2, 3].includes(item.prizeNo)) {
          list.push(item)
        }
      })
      // 按照奖品序号排序
      list.sort((a, b) => {
        return a.prizeNo - b.prizeNo
      })
      return list
    },
    lis2Img () {
      let row = {}
      this.prizesList.forEach(item => {
        if (item.prizeNo === 4) {
          row.imgUrl = item.imgUrl
          row.prizeName = item.prizeName
        }
      })
      return row
    },
    lis3Img () {
      let row = {}
      this.prizesList.forEach(item => {
        if (item.prizeNo === 5) {
          row.imgUrl = item.imgUrl
          row.prizeName = item.prizeName
        }
      })
      return row
    },
    lis4 () {
      let list = []
      this.prizesList.forEach(item => {
        if (item.prizeNo === 6) {
          list[0] = item
        }
        if (item.prizeNo === 7) {
          list[1] = item
        }
        if (item.prizeNo === 8) {
          list[2] = item
        }
      })
      return list
    }
  },
  created () {
    this.speedData = this.speed
    this.afterLotteryHandler = this.afterLottery
  },
  beforeDestroy () {
    this.afterLotteryHandler = () => { }
  },
  methods: {
    startLottery () {
      if (!this.lotteryBtn.lock) {
        let promise = () => {
          return new Promise((resolve, reject) => {
            this.lotteryBtn.lock = true
            this.beforeLottery(resolve, reject)
          })
        }

        let start = async () => {
          try {
            await promise()

            this.roll()
          } catch (e) {
            e()
          }
        }

        start()
      }
    },
    _rollHandler () {
      var index = this.index
      var count = this.count

      for (let i = 0, len = this.activeClass.length; i < len; i++) {
        this.activeClass[i] = false
      }
      index += 1
      if (index > count - 1) {
        index = 0
      }
      this.activeClass[index] = true
      this.index = index
      return false
    },
    roll () {
      // eslint-disable-next-line
      this.activeClass = this.activeClass.map(item => item = false);
      this.times += 1
      this._rollHandler()
      if (this.times > this.cycle + 10 && this.prize === this.index) {
        clearTimeout(this.timer)

        setTimeout(
          () => { this._showResult() }
          , 1000)

        this.lotteryBtn.lock = false
        this.index = -1
        this.count = 8
        this.timer = null
        this.speedData = this.speed
        this.times = 0
      } else {
        if (this.times < this.cycle) {
          this.speedData -= 2
        } else {
          if (this.times > this.cycle + 10 && ((this.prize === 0 && this.index === 7) || this.prize === this.index + 1)) {
            this.speedData += 110
          } else {
            this.speedData += 20
          }
        }
        if (this.speedData < 40) {
          this.speedData = 40
        }
        this.timer = setTimeout(
          () => { this.roll() }
          , this.speedData)
      }
      return false
    },
    _showResult () {
      this.afterLotteryHandler()
    }
  }
}
</script>

  lottery.scss

.iv-lottery {
  ul {
    margin: 0 auto;
    padding:87px 0 0 50px;
    li {
      overflow:hidden;
      position: relative;
      margin-top:8px;
    }
    li div {
      width:177px;
      height:177px;
      position: relative;
      border-radius: 6px;
      float: left;
      margin-left:8px;
      text-align:center;
      // &.prize{
      //   background:#fffafa;
      // }
      &.active:before {
        content: '';
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 5px;
        background: rgba(255, 135, 46, 0.62); }
      }
      img{
        width:102px;
        height:102px;
        margin-top:18px;
        &.img-btn{
          width:209px;
          height:160px;
          position: absolute;
          left:50%;
          margin-left:-100px;
          // top:-10px;
        }
      }
      p{
        &.prizeName{
          color: #f15c38;
          font-size:22px;
        }
        &.gold{
          line-height:28px;
          margin-top:-8px;
        }
      }
      .luck-btn{
        margin-left:0;
        .luck-btn-txt{
          font-size: 75px;
          color: #f87036;
          padding-top:20px;
        }
        .prizeName{
          color: #d92a00;
        }
      }
  }
}

二、引入抽奖组件

<template>
  <div class="lottery-module">
    <p>九宫格抽奖</p>
    <lottery :beforeLottery="beforeLottery"
      :lotteryBtn="lotteryBtn"
      :prizesList="prizesList"
      :prize="prize"
      :afterLottery="afterLottery"></lottery>
  </div>
</template>

<script>
import lottery from '@/components/lottery'
export default {
  name: 'Lottery',
  components: {
    lottery
  },
  data () {
    return {
      prize: 0,
      lotteryBtn: {
        img: '',
        lock: false
      },
      prizesList: [
        {imgUrl: require('@/assets/logo.png'), prizeNo: 1, prizeName: '1'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 2, prizeName: '2'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 3, prizeName: '3'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 4, prizeName: '4'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 5, prizeName: '5'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 6, prizeName: '6'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 7, prizeName: '7'},
        {imgUrl: require('@/assets/logo.png'), prizeNo: 8, prizeName: '8'}
      ],
      count: 0
    }
  },
  mounted () {
    // this.getData()
  },
  methods: {
    getData () {
      // 请求接口开始----九宫格抽奖详情
      // 次数为0,抽奖按钮置灰,不能抽奖
      if (this.count === 0) {
        this.lotteryBtn.lock = true
      } else {
      }
    },
    beforeLottery (resolve, reject) {
      /*
    * send ajax to get result and pass to child component
    **/

      // get result : this.prize
      setTimeout(() => {
        // 调用抽奖接口开始 ----------
        console.log('抽奖开始===========')
        // 中奖序号
        this.prize = this.lotteryPrize(2)
        // 抽奖开始
        resolve()
      }, 10)
    },
    // 抽奖九宫格抽奖位置
    lotteryPrize (prizeNo) {
      let prize
      switch (prizeNo) {
        case 1:
          prize = 0
          break
        case 2:
          prize = 1
          break
        case 3:
          prize = 2
          break
        case 4:
          prize = 7
          break
        case 5:
          prize = 3
          break
        case 6:
          prize = 6
          break
        case 7:
          prize = 4
          break
        default:
          prize = 5
      }
      return prize
    },
    // 抽奖结束
    afterLottery () {
      // 抽奖结果
      alert(`恭喜抽中${this.prize}`)
    }
  }
}
</script>
<style scoped>
</style>

 

原文地址:https://www.cnblogs.com/adbg/p/14042071.html