As the New Year is approaching, I wish you all a happy and prosperous New Year in advance. Many of you have already had a memorable or boring annual party, so here comes the belated lottery component, 233333333

data

Let’s take a look at some of the data we’re going to use

data () {
    return {
      bgStatus: true, // Control the flashing of the lottery borderbgInterval: ' '// Store background switchsetPrizeList: [], // List of prizes to render idList: [], // Array of prize ids to store cur: undefined, // Speed: 100, // speed couldClick:true// Control the clickable state of the lottery button}}Copy the code

Let’s take a look ata structure of data, using variable comments, and then if you have any questions you can go here

template

Take a look at our template structure

<template>
  <div class="md-div"> <! ----------- run ma deng -------------> <div class="md-bd-bg" :class="bgStatus ? 'md-bd-bg1' : 'md-bd-bg2'"> <! ---------- raffle container --------------> <div class="item-out"> <! ---------- circular award --------------> <div class="prize-item flex-column flex-just-center flex-align-center" v-for="k in prizeList" :key="k.prizeid"
             :class="k.prizeid === cur ? 'prize-y' : 'prize-n'"
        >
          <div class="prize-img flex-row flex-just-end flex-align-center">
            <img :src="`https://${k.photo}`" alt=""> </div> <! -- <div class="prize-word">{{k.prize_name}}</div>--> </div> <! ----------- raffle button -------------> <div class="prize-btn" @click="doPrize" :class="couldClick ? '' : 'refuse-click'"></div>
      </div>
    </div>
  </div>
</template>
Copy the code

To analyze the structure, we give an outer layer (class= MD-BD-bg) to be used as the flicker control for the outer light. Here it is very simple, all we need is two images with almost the same background

.md-bd-bg1{background-image: url(".. /.. /statics/tbIcon/shine1.png")}
.md-bd-bg2{background-image: url(".. /.. /statics/tbIcon/shine2.png")}
.md-bd-bg{
  width: 100%;
  height: 100%;
  background-size: 100% 100%;
  padding: 6vw;
}
Copy the code

This is the style of the outer border, mD-BD-BG1 and MD-BD-BG2 correspond to the two states respectively, the next step is to make it move

    controlBg() {// Background transform functionlet vm = this
      vm.bgInterval = setInterval(() => { vm.bgStatus = ! vm.bgStatus }, 500) }Copy the code

We use bgInterval to store a setInterval. The reason we use a variable to store a setInterval is to clear events when cleaning components

To the chase!

Finally to our serious horse light lottery, the first analysis of the structure

<! ---------- circular award --------------> <div class="prize-item flex-column flex-just-center flex-align-center" v-for="k in prizeList" :key="k.prizeid"
             :class="k.prizeid === cur ? 'prize-y' : 'prize-n'"
        >
          <div class="prize-img flex-row flex-just-end flex-align-center">
            <img :src="`https://${k.photo}`" alt=""> </div> <! -- <div class="prize-word">{{k.prize_name}}</div>-->
        </div>
Copy the code

Loop render the requested array of prizes using V-for

.prize-y{background-image: url(".. /.. /statics/tbIcon/prize_y.png"); } .prize-n{background-image: url(".. /.. /statics/tbIcon/prize_n.png")} .prize-item:nth-of-type(1){top: .1vw; left: .1vw; } .prize-item:nth-of-type(2){top: .1vw; Left: 27.35 vw; } .prize-item:nth-of-type(3){top: .1vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (4) {top: 27.35 vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (5) {top: 54.6 vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (6) {top: 54.6 vw; Left: 27.35 vw; }. Prize - item: the NTH - of - type (7) {top: 54.6 vw; left: .1vw; }. Prize - item: the NTH - of - type (8) {top: 27.35 vw; left: .1vw; }Copy the code

Vw units are used here. Vw, VH, Vmin and vmax are all used. The above code places the awards in a circle, leaving space for buttons

.prize-btn{width: 27vw; height: 27vw; background-size: 100% 100%; position: absolute; background-image: url(".. /.. /statics/tbIcon/prize-btn.png"); Top: 27.35 vw; Left: 27.35 vw; }Copy the code

All right, with everything in place, let’s have fun writing logic

Click on the draw

Check out our lucky draw button

<template>
    <div class="prize-btn" @click="doPrize" :class="couldClick ? '' : 'refuse-click'"> < / div > < / template > / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- forbid click -- -- -- -- -- -- -- -- -- -- -- -- - * /. Refuse - click {filter: grayscale (10%). } | | \ | | / / /doPrize () {
      let vm = this
      if (vm.couldClick) {
        vm.couldClick = false// Disallows the next drawing vm before the first drawing is completed.$axios(urls.doPrize, {}).then(res => {
          let code = res.code
          if (code === 'success') {
            vm.prizeAnimate(res)
          } else {
            vm.$q.notify({ message: res.msg })
          }
        })
      }
    }
Copy the code

When clicked, it will be the primary color of the design drawing, and when not clicked, it will be a gray filter. CSS filter is also very interesting. But first to the service to request the result of the lottery, that is to say, the animation behind are redundant, you click on the time has already determined your winning result, so we don’t write animation, so we can directly use

Continue to

Just as a joke, I pasted my raffle animation code

prizeAnimate (result) {
      let vm = this
      vm.cur = undefined
      let num = vm.idList.indexOf(Number(result.prizeid))
      let len = vm.idList.length
      letAllSteps = math.floor (math.random () * 3 + 2) * len + num // Total number of steps to take 2~5let a = 0
      function myInt () {
        setTimeout(() => {
          if(a <= allSteps) {// A is the number of steps that have been takenif(allSteps -a < len * 2 && allSteps -a >= len) {// Enter the penultimate circle, add delay vm.speed = 200}else if(allSteps -a < len) {// Enter the penultimate circle and add the delay vm.speed = 400} vm.cur = vm.idList[a % vm.idlist.length] // A++ // after performing the jump, remember to add 1 to the number of jumps myInt() // recursive call}else{// Finally finish the vm.couldClick =trueVm. speed = 100 // Restore the speed // ------- // lottery animation to complete the next operation, such as popup notification of winning the lottery}}, vm.speed)} myInt()}}Copy the code

In the first step, we empty cur, and then extract the index value of the winning result in the prize array, which is the allSteps used to generate the total number of steps. To make the animation look as’ we really animated it ‘as possible, we set 2 to 5 turns plus the index value, and now we have the total number of steps to take

So start

Here I declare myInt to be used as the body of a recursive setTimeout function. The purpose of this is, first of all, our lottery is animated, so the speed must not be uniform. If we use setInterval, changing the speed will not change the beating speed of the animation. SetInterval can also be used, but you have to write three, a fast, a medium speed, a low speed, and then execute one by one. Haha, I would like to explain this function again, but I feel like it is written in the remarks, so I will pack up and go home for Chinese New Year, 886~~

The whole assembly is served

<template>
  <div class="md-div">
    <div class="md-bd-bg" :class="bgStatus ? 'md-bd-bg1' : 'md-bd-bg2'">
      <div class="item-out">
        <div class="prize-item flex-column flex-just-center flex-align-center" v-for="k in prizeList" :key="k.prizeid"
             :class="k.prizeid === cur ? 'prize-y' : 'prize-n'"
        >
          <div class="prize-img flex-row flex-just-end flex-align-center">
            <img :src="`https://${k.photo}`" alt=""> </div> <! -- <div class="prize-word">{{k.prize_name}}</div>--> </div> <! ----------- raffle button -------------> <div class="prize-btn" @click="doPrize" :class="couldClick ? '' : 'refuse-click'"></div>
      </div>
    </div>
  </div>
</template>

<script>
import urls from 'src/api/urls'
export default {
  name: 'module'.data () {
    return {
      bgStatus: true.bgInterval: ' 'IdList: [], cur: undefined, couldClick:true// The lucky draw button can be clicked}},created () {
    letVm = this vm.controlBg() // open background transform vm.queryList() // request award}, methods: {controlBg() {// Background transform functionlet vm = this
      vm.bgInterval = setInterval(() => { vm.bgStatus = ! vm.bgStatus }, 500) },queryList () {
      let vm = this
      vm.$axios(urls.getPrizeList, {}).then(res => {
        let code = res.code
        if (code === 'success') {
          // console.log(res)
          for (let k in res.lottery_prize) {
            vm.idList.push(res.lottery_prize[k].prizeid)
          }
          vm.prizeList = res.lottery_prize
          vm.$emit('subNotice', res)
        } else {
          vm.$router.go(-1)
        }
      })
    },
    doPrize () {
      let vm = this
      if (vm.couldClick) {
        vm.couldClick = false// Disable vm execution immediately next time.$axios(urls.doPrize, {}).then(res => {
          let code = res.code
          if (code === 'success') {
            vm.prizeAnimate(res)
          } else {
            vm.$q.notify({ message: res.msg })
          }
        })
      }
    },
    prizeAnimate (result) {
      let vm = this
      vm.cur = undefined
      let num = vm.idList.indexOf(Number(result.prizeid))
      let len = vm.idList.length
      letAllStamps = math.floor (math.random () * 3 + 2) * len + num // The total number of steps to take 2~5let a = 0
      function myInt () {
        setTimeout(() => {
          if (a <= allStamps) {
            if (allStamps - a < len * 2 && allStamps - a >= len) {
              vm.speed = 200
            } else if (allStamps - a < len) {
              vm.speed = 400
            }
            vm.cur = vm.idList[a % vm.idList.length]
            a++
            myInt()
          } else {
            vm.couldClick = true
            vm.$emit('subDc', result)
            vm.speed = 100
          }
        }, vm.speed)
      }
      myInt()
    }
  }
}
</script>

<style scoped>
.md-div{
  width: 94vw;
  height: 94vw;
  position: relative;
  margin: 3vw;
}
.md-bd-bg1{background-image: url(".. /.. /statics/tbIcon/shine1.png")}
.md-bd-bg2{background-image: url(".. /.. /statics/tbIcon/shine2.png")} .md-bd-bg{ width: 100%; height: 100%; background-size: 100% 100%; padding: 6vw; } .item-out{width: 100%; height: 100%; position: relative; } .prize-item{ width: 27vw; height: 27vw; background-size: 100% 100%; position: absolute; } .prize-btn{width: 27vw; height: 27vw; background-size: 100% 100%; position: absolute; background-image: url(".. /.. /statics/tbIcon/prize-btn.png"); Top: 27.35 vw; Left: 27.35 vw; } .prize-img{width: 70%; height: 40%; } .prize-img img{width: 100%; height: auto; } .prize-word{color:# 832909; The font - size: 1.4 rem; }
.prize-y{background-image: url(".. /.. /statics/tbIcon/prize_y.png"); } .prize-n{background-image: url(".. /.. /statics/tbIcon/prize_n.png")} .prize-item:nth-of-type(1){top: .1vw; left: .1vw; } .prize-item:nth-of-type(2){top: .1vw; Left: 27.35 vw; } .prize-item:nth-of-type(3){top: .1vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (4) {top: 27.35 vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (5) {top: 54.6 vw; Left: 54.6 vw; }. Prize - item: the NTH - of - type (6) {top: 54.6 vw; Left: 27.35 vw; }. Prize - item: the NTH - of - type (7) {top: 54.6 vw; left: .1vw; }. Prize - item: the NTH - of - type (8) {top: 27.35 vw; left: .1vw; } / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- forbid click -- -- -- -- -- -- -- -- -- -- -- -- - * /. Refuse - click {filter: grayscale (10%). } </style>Copy the code