Vue3實(shí)現(xiàn)九宮格抽獎(jiǎng)的示例代碼
前言
對(duì)象說晚飯吃什么太難選擇,問我能不能做一個(gè)九宮格抽獎(jiǎng)來決定我們晚上吃什么,emmm。
既然對(duì)象都開口了,不做也不行啊,最后給大家看一個(gè)簡(jiǎn)化版的(沒有美工樣式、編輯獎(jiǎng)品這些)

前期構(gòu)思
首先是布局,這個(gè)比較簡(jiǎn)單,用彈性布局(flex)就足夠了,抽獎(jiǎng)盒子固定寬高,獎(jiǎng)品項(xiàng)為盒子的1/3,超過換行就行,轉(zhuǎn)動(dòng)方向是這樣的:

抽獎(jiǎng)方式主要分為兩種,一種是隨機(jī)抽?。ㄍ耆S機(jī)),還有一種是指定獎(jiǎng)品抽?。úm著女朋友加的功能??,為了以后能吃到自己喜歡的東西)
轉(zhuǎn)動(dòng)速度的規(guī)則是:加速 -> 勻速 -> 減速。
代碼實(shí)現(xiàn)用了 vue3。
具體實(shí)現(xiàn)
1、布局
布局采用彈性布局,利用 vue 的 v-for 動(dòng)態(tài)生成九個(gè) item ,select 樣式是用來控制轉(zhuǎn)動(dòng)的時(shí)候當(dāng)前選中的 item。
這里循環(huán)的key值,我使用的索引值,主要是為了后面添加編輯獎(jiǎng)品的時(shí)候,id不一定能保證按順序排列,所以用索引值比較直觀。
<template>
<div class="box">
<div v-for="(item, index) in raffleItem" :key="index" :class="{item: true, select: selectItem === index}">{{ item.name }}</div>
</div>
<button @click="startRaffle">開始抽獎(jiǎng)</button>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
// 獎(jiǎng)品
const raffleItem = [
{name: '法拉利', id: 1},
{name: '蘭博基尼', id: 2},
{name: '保時(shí)捷', id: 3},
{name: '寶馬', id: 4},
{name: '悍馬人', id: 5},
{name: '紅旗', id: 6},
{name: '特斯拉', id: 7},
{name: '比亞迪', id: 8},
{name: '奔馳', id: 9}
]
// 選中的item
const selectItem = ref(0)
return {
raffleItem,
selectItem
}
},
});
</script>
<style>
.box {
width: 300px;
height: 300px;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.item {
width: 95px;
height: 95px;
}
.box, .item {
box-sizing: border-box;
border: 1px solid;
border-radius: 5px;
}
.select {
border-color: red;
color: red;
background: #579393;
}
</style>2、指定獎(jiǎng)品
為每一個(gè) item 添加單機(jī)事件 appoint(index),傳入?yún)?shù)為當(dāng)前的索引值。
做成點(diǎn)擊事件指定獎(jiǎng)品主要是為了不讓對(duì)象發(fā)現(xiàn)
// 指定的獎(jiǎng)品
const appointRaffle = ref(null)
// 指定獎(jiǎng)品
const appoint = (index) => {
appointRaffle.value = index
}3、抽獎(jiǎng)
抽獎(jiǎng)的具體實(shí)現(xiàn):
- 利用定時(shí)器
setTimeout控制轉(zhuǎn)動(dòng)速度speed - 轉(zhuǎn)動(dòng)速度(speed)的規(guī)則為,通過圈數(shù)跟中獎(jiǎng)項(xiàng)計(jì)算出總的轉(zhuǎn)動(dòng)次數(shù),然后先加速再勻速最后減速
- 利用樣式規(guī)則來控制選中的 item
selectItem - 轉(zhuǎn)動(dòng)的圈數(shù)量
activeTurns通過隨機(jī)數(shù)取10~20 - 中獎(jiǎng)的規(guī)則:圈數(shù)跟需要轉(zhuǎn)動(dòng)的總?cè)?shù)相同并且轉(zhuǎn)到本輪中獎(jiǎng)的位置則停止轉(zhuǎn)動(dòng)表示中獎(jiǎng)
- 每次抽獎(jiǎng)前需要初始化各種狀態(tài)值,如:選中的item(selectItem)、當(dāng)前中獎(jiǎng)(activeRaffle)...
- 如果已經(jīng)在抽獎(jiǎng),開始抽獎(jiǎng)按鈕就會(huì)失效
// 指定的獎(jiǎng)品
const appointRaffle = ref(null)
// 指定獎(jiǎng)品
const appoint = (index) => {
appointRaffle.value = index
}
// 當(dāng)前中獎(jiǎng)
const activeRaffle = ref(null)
// 選中的item
const selectItem = ref(0)
// 定時(shí)器
const timer = ref(null)
// 圈數(shù)
const turnsNumbers = ref(0)
// 轉(zhuǎn)多少圈中獎(jiǎng)
const activeTurns = ref(0)
// 初始轉(zhuǎn)動(dòng)速度
const speed = ref(100)
// 剩余幾個(gè)中獎(jiǎng)
const surplusNum = computed(() => {
// 剩余圈數(shù) * 9 + 指定中獎(jiǎng)的索引
return (activeTurns.value - turnsNumbers.value) * 9 + appointRaffle.value - selectItem.value
})
// 初始化
const init = () => {
selectItem.value = 1
activeTurns.value = 0
turnsNumbers.value = 0
speed.value = 100
activeRaffle.value = null
}
// 開始抽獎(jiǎng)
const startRaffle = () => {
// 如果已經(jīng)存在定時(shí)器則表示已經(jīng)在轉(zhuǎn)動(dòng),不理會(huì)
if(timer.value) return
// 初始化
init()
// 如果沒有指定獎(jiǎng)品則隨機(jī)指定一個(gè)獎(jiǎng)品
if(!appointRaffle.value) {
// 取隨機(jī)數(shù)0-8,數(shù)組的索引值
appointRaffle.value = Math.round(Math.random() * 8)
}
// 取隨機(jī)數(shù)10~20圈,id > 4時(shí)少轉(zhuǎn)一圈
const num = Math.round(Math.random()*10) + 10
activeTurns.value = appointRaffle.value > 4 ? num - 1 : num
// 抽獎(jiǎng)
handleRaffle()
}轉(zhuǎn)動(dòng)的方法實(shí)現(xiàn)
這里需要注意的是,我們使用的是索引值,所以轉(zhuǎn)動(dòng)一圈為0~8,而不是1~9
// 抽獎(jiǎng)方法
const handleRaffle = () => {
// 每轉(zhuǎn)完一圈
if (selectItem.value === 8) {
turnsNumbers.value ++
selectItem.value = 0
} else {
selectItem.value ++
}
// 轉(zhuǎn)動(dòng)速度規(guī)則
speed.value = speedRole()
// 如果圈數(shù)跟需要轉(zhuǎn)動(dòng)的總?cè)?shù)相同并且轉(zhuǎn)到本輪中獎(jiǎng)的位置則停止轉(zhuǎn)動(dòng)
if (activeTurns.value === turnsNumbers.value && selectItem.value === appointRaffle.value) {
// 中獎(jiǎng)
activeRaffle.value = raffleItem[appointRaffle.value].name
// 清除定時(shí)器
clearTimeout(timer.value)
timer.value = null
// 清除指定中獎(jiǎng)項(xiàng)
appointRaffle.value = null
} else {
// 定時(shí)器
timer.value = setTimeout(handleRaffle, speed.value)
}
}轉(zhuǎn)動(dòng)規(guī)則的方法
轉(zhuǎn)動(dòng)速度分為4個(gè)階段
- 前面的 1/3 加速轉(zhuǎn)動(dòng)
- 中間的 1/3 是勻速轉(zhuǎn)動(dòng)
- 后面的 1/3 是減速轉(zhuǎn)動(dòng)
- 最后的 9 個(gè)速度降低到 300 轉(zhuǎn)動(dòng)
經(jīng)過計(jì)算,在圈數(shù)的分為內(nèi),最后的減速轉(zhuǎn)動(dòng),不能把速度減少到 300 之上,所以不會(huì)出現(xiàn)最后 9 個(gè)加速轉(zhuǎn)動(dòng)的情況
// 轉(zhuǎn)動(dòng)速度規(guī)則-先加速在勻速最后減速
const speedRole = () => {
const total = activeTurns.value * 9 + appointRaffle.value
// 剩余最后9個(gè)中獎(jiǎng)時(shí)的時(shí)候速度降低到300
if(surplusNum.value <= 9) return 300
// 前3/1加速轉(zhuǎn)動(dòng)
if(surplusNum.value >= total * 2 / 3) return speed.value <= 50 ? 50 : speed.value - 2
// 最后的3/1減速每次+1
if(surplusNum.value <= total / 3) return speed.value + 1
// 剩余的中間勻速
return speed.value
}最終效果

以上就是Vue3實(shí)現(xiàn)九宮格抽獎(jiǎng)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue九宮格抽獎(jiǎng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于Vue uniapp實(shí)現(xiàn)貪吃蛇游戲
貪吃蛇游戲想必是很多70、80后的回憶,一直到現(xiàn)在也深受大家的喜歡。本文將利用Vue+uniapp實(shí)現(xiàn)這一經(jīng)典的游戲,感興趣的可以了解一下2022-04-04
VUE接入騰訊驗(yàn)證碼功能(滑塊驗(yàn)證)備忘
這篇文章主要介紹了VUE接入騰訊驗(yàn)證碼功能(滑塊驗(yàn)證)備忘,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
基于Vue實(shí)現(xiàn)本地消息隊(duì)列MQ的示例詳解
這篇文章為大家詳細(xì)主要介紹了如何基于Vue實(shí)現(xiàn)本地消息隊(duì)列MQ, 讓消息延遲消費(fèi)或者做緩存,文中的示例代碼講解詳細(xì),需要的可以參考一下2024-02-02
Vuejs第六篇之Vuejs與form元素實(shí)例解析
本文通過實(shí)例給大家詳細(xì)介紹了Vuejs與form元素的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Vue 解決父組件跳轉(zhuǎn)子路由后當(dāng)前導(dǎo)航active樣式消失問題
這篇文章主要介紹了Vue 解決父組件跳轉(zhuǎn)子路由后當(dāng)前導(dǎo)航active樣式消失問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Vue2.0表單校驗(yàn)組件vee-validate的使用詳解
本篇文章主要介紹了Vue2.0表單校驗(yàn)組件vee-validate的使用詳解,詳細(xì)的介紹了vee-validate使用教程。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05

