抽奖动画及逻辑

 

<view class="container_box">
  <view class="container_active">
    <view class="container_active_item" v-for="(item, index) in gridItems" :key="index" :class="{ active: index === activeIndex }">
      <text v-if="index !== 4">{{ item }}</text>
      <view class="container_active_btn" :class="{ active: isActive1 }" v-else @tap="startLottery('1')">开始抽奖</view>
    </view>
  </view>
  <view class="container_machineBtn" :class="{ active: isActive2 }" @tap="startLottery('2')">开始抽奖</view>
  <image class="container_machineIcon" :class="{ active: isActive2 }" src="@static/img/machine-btn.png"></image>
</view>
 <!-- 弹窗 -->
 <view class="container_window" v-if="raffleShow">
      <!-- 中奖 -->
      <view v-if="goodShow">
        <image class="container_window_goodIcon" src="@static/img/raffle-bg.png"></image>
        <view class="container_window_name">券1及券2</view>
        <view class="container_window_number">
          <view>
            <view>券1</view>
            <view style="margin: 10rpx 0">{{ goodData.rewardConpons || 0 }}张</view>
          </view>
          <view style="margin: 10rpx 0">
            <view>券2</view>
            <view style="margin: 10rpx 0">{{ goodData.rewardQuasiTickets || 0 }}张</view>
          </view>
        </view>
        <image class="container_window_receiveIcon" src="@static/img/receive.png" @click="clockShow"></image>
      </view>
      <!-- 不中奖 -->
      <view v-if="badShow">
        <image class="container_window_goodIcon" src="@static/img/bad.png"></image>
        <image class="container_window_receiveIcon" src="@static/img/back.png" @click="clockShow"></image>
      </view>
    </view>
data(){
 return{
    gridItems: ['谢谢参与', '恭喜您中奖啦', '谢谢参与', '恭喜您中奖啦', '开始抽奖', '恭喜您中奖啦', '谢谢参与', '恭喜您中奖啦', '谢谢参与'],
    activeIndex: -1,
    isRunning: false,
    sequence: [0, 1, 2, 5, 8, 7, 6, 3], // 顺时针旋转顺序
   this.goodData:null,
  raffleShow: false,
  goodShow: false,
  badShow: false,
  isActive1: false,
  isActive2: false,
 }
}
methods:{
     async startLottery(num) {
      if (num == '1') {
        this.isActive1 = !this.isActive1
        setTimeout(() => {
          this.isActive1 = false // 动画结束后重置状态
        }, 500) // 假设动画持续时间为500ms
      } else if (num == '2') {
        this.isActive2 = !this.isActive2
        setTimeout(() => {
          this.isActive2 = false // 动画结束后重置状态
        }, 500) // 假设动画持续时间为500ms
      }
      let respon = await ala.httpGet(接口)
      this.goodData = respon
      let probability = false
      if (respon) {
        if (this.isRunning) return
        this.isRunning = true
        let count = 0
        const totalSteps = Math.floor(Math.random() * 20) + 30 // 随机步数
        const interval = setInterval(
          () => {
            this.activeIndex = this.sequence[count % this.sequence.length]
            count++
            if (count === totalSteps) {
                // winningLottery后端返回的用户中奖
              if (this.goodData.isWinner == 'winningLottery') {
                probability = Math.random() > 0 // 100% 的中奖概率
              } else {
                probability = Math.random() > 1 // 0% 的中奖概率
              }
            }
            if (count >= totalSteps) {
              clearInterval(interval)
              this.isRunning = false
              this.raffleShow = true
              if (probability) {
                this.goodShow = true
                this.badShow = false
              } else {
                this.badShow = true
                this.goodShow = false
              }
            }
          },
          100 - Math.floor((count / totalSteps) * 80)
        )
      }
    },
}
<style>
    .container{
        &_active {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 10rpx;
    width: 75%;
    height: 500rpx;
    margin: 40rpx auto 0 auto;
    color: #e4362a;
    padding: 20rpx 0 10rpx 25rpx;
    &_item {
      display: flex;
      justify-content: center;
      align-items: center;
      text-align: center;
      padding: 20rpx 30rpx 20rpx 30rpx;
      width: 150rpx;
      height: 140rpx;
      font-size: 30rpx;
      transition: background 0.3s;
      font-weight: bold;
      &:nth-child(1) {
        padding: 15rpx 40rpx 20rpx 40rpx;
      }
      &:nth-child(2) {
        padding: 15rpx 34rpx 20rpx 26rpx;
      }
      &:nth-child(3) {
        padding: 20rpx 40rpx 20rpx 30rpx;
      }
      &:nth-child(7) {
        padding: 40rpx 40rpx 20rpx 40rpx;
      }
      &:nth-child(8) {
        padding: 40rpx 30rpx 20rpx 30rpx;
      }
      &:nth-child(9) {
        padding: 40rpx 50rpx 20rpx 30rpx;
      }
    }
    &_item.active {
      color: #fff;
    }
    &_btn {
      font-size: 40rpx;
      cursor: pointer;
      color: #a55818;
      font-weight: bold;
      margin-right: 10rpx;
      transition:
        transform 0.2s,
        box-shadow 0.2s;
      &.active {
        transform: scale(1.1);
        animation: duang1 0.5s ease-out;
      }
    }
    @keyframes duang1 {
      0% {
        transform: scale(0.5);
      }
      30% {
        transform: scale(1);
      }
      50% {
        transform: scale(1.5);
      }
      100% {
        transform: scale(1);
      }
    }
  }
  &_machineBtn {
    font-size: 40rpx;
    font-weight: bold;
    color: #fff;
    z-index: 9;
    position: absolute;
    bottom: 16%;
    left: 40%;
    transform: rotateX(40deg);
    transition:
      transform 0.2s,
      box-shadow 0.2s;
    &.active {
      transform: scale(1.1);
      animation: duang2 0.5s ease-out;
    }
  }
  @keyframes duang2 {
    0% {
      transform: scale(0.5);
    }
    30% {
      transform: scale(1);
    }
    50% {
      transform: scale(1.5);
    }
    100% {
      transform: scale(1);
    }
  }
  &_machineIcon {
    width: 290rpx;
    height: 100rpx;
    margin-left: 30%;
    margin-top: 55rpx;
    transition:
      transform 0.2s,
      box-shadow 0.2s;
    &.active {
      transform: scale(1.1);
      animation: duang2 0.5s ease-out;
    }
  }
&_window {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 99;
    background: #000000b6;
    &_goodIcon {
      width: 100%;
      height: 800rpx;
      margin-top: 20%;
    }
    &_name {
      position: absolute;
      left: 33%;
      top: 520rpx;
      letter-spacing: 6rpx;
      font-weight: 600;
      color: rgba(255, 40, 15);
    }
    &_number {
      position: absolute;
      color: #fff4d3;
      width: 430rpx;
      height: 150rpx;
      text-align: center;
      font-weight: 500;
      font-size: 35rpx;
      left: 25%;
      top: 600rpx;
      z-index: 99;
      letter-spacing: 10rpx;
      display: flex;
      justify-content: space-around;
      align-items: center;
    }
    &_receiveIcon {
      position: absolute;
      width: 281rpx;
      height: 74rpx;
      left: 33%;
      z-index: 99;
      top: 41%;
    }
  }
    }
</style>

 

posted @ 2025-04-17 17:38  挽你手  阅读(29)  评论(0)    收藏  举报