Vue3 实现九宫格抽奖组件

实现思路:首先最简单的HTML 布局,使用了 flex 布局,同时利用一个定时器,动态控制选中的项,1,2,3,4,5,6,7,8,循环选中,我这里写得比较垃圾,就是判断一直让 active 项加加,然后遇到 8 的时候,就重置 为 1 ,看来其就是连贯的效果;然后还有先慢再快再慢的效果, 我是判断了 定义的定时器的时间除以5,也就是 每次执行代码都是对时间相减一定的数量,这样定时器执行时间就会变短,当大于这个 时间除以5,就对当前时间进行相加,也就是定时器会变慢执行,直接上码看看吧

 

<template>
  <div class="luckDraw-container">
    <div v-for="item in dataList" :key="item.key" class="luckDraw-item" :class="{ active: activeIndex === item.key }" @click="() => start(item)">
      <div>
        {{ item.content ? item.content : '开始' }}
        {{ item.key }}
      </div>
    </div>
    <div> 中奖号码:{{ winActive }} </div>
  </div>
</template>

<script lang="ts" setup name="luckDraw">
import { onMounted, reactive, ref } from 'vue';
const props = defineProps({
  // 速度
  speed: {
    type: Number,
    default: 200
  }
});

// 随机选中一个开始进行抽奖
const activeIndex = ref(null);

const dataList = reactive([
  {
    key: 1,
    content: '谢谢惠顾'
  },
  {
    key: 2,
    content: '一等奖'
  },
  {
    key: 3,
    content: '谢谢惠顾'
  },
  {
    key: 8,
    content: '谢谢惠顾'
  },
  {
    key: 0
  },
  {
    key: 4,
    content: '三等奖'
  },
  {
    key: 7,
    content: '谢谢惠顾'
  },
  {
    key: 6,
    content: '二等奖'
  },
  {
    key: 5,
    content: '谢谢惠顾'
  }
]);

// 中奖号码
const winActive = ref(null);

// 定时器
const timer = ref(null);

// 速度
const speed = ref(props.speed);

// 点击开始
function start(item: { key: number; content: string }) {
  if (timer.value || item.key != 0) return;
  if (!activeIndex.value) {
    activeIndex.value = parseInt(Math.random() * 8 + 1);
  }
  winActive.value = parseInt(Math.random() * 8 + 1);
  luckDraw();
}

const lock = ref(false);
// 抽奖成功
function luckDraw() {
  if (speed.value > 0) {
    // 控制九宫格选中的速度,当速度是当前的五分之一的时候,就让速度变慢
    const half = parseInt(props.speed / 5);
    if (lock.value) {
      speed.value += 5;
      if (speed.value >= props.speed) {
        // 中奖一共八个宫格,如果中奖在其他的宫格,就多加几个 步速,一直到中奖
        if (winActive.value === activeIndex.value) {
          clearInterval(timer.value);
          speed.value = props.speed;
          timer.value = null;
          lock.value = false;
          return;
        }
      }
      // 速度再加快
    } else if (!lock.value) {
      speed.value -= 5;
      if (half >= speed.value) {
        lock.value = true;
      }
    }

    // 选中样式
    if (activeIndex.value == 8) activeIndex.value = 1;
    else activeIndex.value++;

    // 执行抽奖方法
    timer.value = setTimeout(luckDraw, speed.value);
  }
}

onMounted(() => {});
</script>

<style lang="scss" scoped>
.luckDraw-container {
  width: 500px;
  height: 500px;
  border-radius: 10px;
  border: 1px solid #000;
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex-wrap: wrap;
  user-select: none;

  .luckDraw-item {
    width: 150px;
    height: 150px;
    border: 1px solid #ccc;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 10px;
    cursor: pointer;
  }
  .active {
    background-color: #ffa500;
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清云随笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值