unibest/src/pages/demo/lottery.vue

127 lines
3.3 KiB
Vue
Raw Normal View History

2024-01-10 16:57:02 +08:00
<route lang="json5">
{
style: { navigationBarTitleText: '九宫格抽奖' },
}
</route>
<template>
<view class="mt-4 h-10 text-center">九宫格抽奖</view>
<view class="lottery-box">
<view class="lottery-list">
<view
class="lottery-item"
:class="{
active: n === activeIndex,
btn: n === btnIndex, // 最中间那个是展示按钮
}"
v-for="n in numList"
:key="n"
@click="handleClick(n)"
>
<view v-if="n === btnIndex">点击抽奖</view>
<view v-else> {{ n }}</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { reactive, computed } from 'vue'
2024-01-10 17:18:55 +08:00
const giftLen = 8 // 九宫格有8个礼物
const loop = 4 // 设置转多少圈,在最后一圈会慢下来
const totalStep = giftLen * loop // 总的步数 32
const lastLoopStep = totalStep - giftLen // 最后一圈24
2024-01-10 16:57:02 +08:00
const numList = [1, 2, 3, 8, -1, 4, 7, 6, 5]
const btnIndex = numList[4] // 最中间那个是展示按钮
const state = reactive({
lottery: 0, // 奖品
step: -1, // 目前转动的步数
2024-01-10 17:18:55 +08:00
stopStep: totalStep, // 停下来的时需要走的步数
2024-01-10 16:57:02 +08:00
speed: 2, // 转动速度,我们是通过定时器去实现转动效果的,所以这也就是定时器的执行频率
timer: null, // 定时器ID
loading: false,
})
// 通过目前转动的步数来对8取模得到当前转到的格子索引
const activeIndex = computed(() => {
return (state.step % 8) + 1
})
2024-01-10 17:18:55 +08:00
function run() {
2024-01-10 16:57:02 +08:00
// 当前步数大于等于目标步数
if (state.step >= state.stopStep) {
// 清空定时器,停止转动
clearTimeout(state.timer)
// 将初始化步数为最终奖品的步数,转动速度也置为初始速度,下次才能正确转动
state.step = state.lottery
state.speed = 2
state.loading = false
2024-01-10 17:18:55 +08:00
console.log(`恭喜获得${activeIndex.value}号奖品`)
uni.showModal({
title: `恭喜获得${activeIndex.value}号奖品`,
})
2024-01-10 16:57:02 +08:00
return
}
// 转动到最后一圈时增加speed也就是定时器执行间隔时间变长转动速度变慢
2024-01-10 17:18:55 +08:00
if (state.step > lastLoopStep + state.lottery) {
2024-01-10 16:57:02 +08:00
state.speed++
}
// 抽奖函数每执行一次,当前步数加一
state.step++
// 重新开启定时器执行抽奖函数
2024-01-10 17:18:55 +08:00
state.timer = setTimeout(run, state.speed * 30)
2024-01-10 16:57:02 +08:00
}
// 点击抽奖之后调用的函数
function handleClick(n) {
if (n !== btnIndex) {
return
}
if (state.loading) return
state.loading = true
// 最终获得的奖品,实际业务中是通过接口获取的,这里使用随机数来模拟下
2024-01-10 17:18:55 +08:00
state.lottery = Math.ceil(Math.random() * giftLen)
2024-01-10 16:57:02 +08:00
console.log(state.lottery)
// 计算总共要转动的步数转4圈后再转到奖品处
2024-01-10 17:18:55 +08:00
state.stopStep = state.lottery + totalStep
2024-01-10 16:57:02 +08:00
// 执行抽奖函数
2024-01-10 17:18:55 +08:00
run()
2024-01-10 16:57:02 +08:00
}
</script>
<style lang="css">
.lottery-box {
display: flex;
align-items: center;
justify-content: center;
}
.lottery-list {
--size: 100px;
display: flex;
flex-wrap: wrap;
width: calc(3 * var(--size) + 3px);
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.lottery-item {
width: var(--size);
height: var(--size);
line-height: var(--size);
text-align: center;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
.lottery-item.active {
color: #fff;
background-color: red;
}
.lottery-item.btn {
cursor: pointer;
}
</style>