最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3實現(xiàn)九宮格抽獎效果的示例詳解

 更新時間:2023年10月09日 10:49:42   作者:Liben  
這篇文章主要為大家詳細介紹了如何通過Vue3實現(xiàn)簡單的九宮格抽獎效果,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的可以了解一下

前言

好久沒有寫文章了,上一次發(fā)文還是年終總結(jié),眨眼間又是一年,每每想多總結(jié)卻是堅持不來,難頂。  這次分享一個九宮格抽獎小游戲,緣起是最近公司內(nèi)部做積分抽獎需求,抽出其中抽獎動效做一個總結(jié),從零實現(xiàn)一個抽獎功能的過程和注意點。

Demo功能代碼是使用vue3實現(xiàn)的,主要用到了組合式API,由于只是一個簡單的demo就沒有使用腳手架和打包工具。

需求與效果

需求: 1、禮品根據(jù)后臺配置生成 2、跑馬燈轉(zhuǎn)動效果 3、結(jié)果后臺生成并且每個禮物概率不一樣(概率這里不討論)

注意點: 1、布局如何排列,是按照跑動排列還是從左至右自上而下排列 2、點擊按鈕如何插入,DOM結(jié)構(gòu)如何生成 3、跑馬效果如何實現(xiàn),速度如何控制 4、接口如何處理,包括接口報錯、請求Pending時特效 5、后臺返回結(jié)果和跑馬完選中結(jié)果一致等

最終效果圖:

注:圖片都是百度圖片找的

功能實現(xiàn)

第一步:實現(xiàn)布局

思路:請求到后臺配置的禮物列表,一般是配置了8個禮物,包括謝謝參與,第一種是手動布局寫9個禮物div標簽,這種方式開始按鈕可以直接寫到布局里面。第二種可以遍歷,這里我使用遍歷的方式,但是按鈕就需要我們插入到禮物列表數(shù)組中去。css代碼可以使用flex布局,三行三列剛好,然后添加所需樣式。js部分主要是使用splice()方法插入<開始按鈕>。

部分代碼:

<body>
  <div id="app" v-cloak>
    <div class="container">
      <div :class="['item', {'active': currentIndex === index}]"
        v-for="(item, index) in prizeList"
        @click="start(index)">
        <img :src="item.pic" alt="">
        <p v-if="index !== 4">{{ item.name }}</p>
      </div>
    </div>
  </div>
</body>
const state = reactive({
  prizeList: [
    { name: '手機', pic: 'https://bkimg.cdn.bcebos.com/pic/3801213fb80e7bec54e7d237ad7eae389b504ec23d9e' },
    { name: '手表', pic: 'https://img1.baidu.com/it/u=2631716577,1296460670&fm=253&fmt=auto&app=120&f=JPEG' },
    { name: '蘋果', pic: 'https://img2.baidu.com/it/u=2611478896,137965957&fm=253&fmt=auto&app=138&f=JPEG' },
    { name: '棒棒糖', pic: 'https://img2.baidu.com/it/u=576980037,1655121105&fm=253&fmt=auto&app=138&f=PNG' },
    { name: '娃娃', pic: 'https://img2.baidu.com/it/u=4075390137,3967712457&fm=253&fmt=auto&app=138&f=PNG' },
    { name: '木馬', pic: 'https://img1.baidu.com/it/u=2434318933,2727681086&fm=253&fmt=auto&app=120&f=JPEG' },
    { name: '德芙', pic: 'https://img0.baidu.com/it/u=1378564582,2397555841&fm=253&fmt=auto&app=120&f=JPEG' },
    { name: '玫瑰', pic: 'https://img1.baidu.com/it/u=1125656938,422247900&fm=253&fmt=auto&app=120&f=JPEG' }
  ], // 后臺配置的獎品數(shù)據(jù)
})
const startBtn = { name: '開始按鈕', pic: 'https://img2.baidu.com/it/u=1497996119,382735686&fm=253' }
onMounted(() => {
  // state.prizeList.forEach((item, index) => {
  //  item.id = index
  // })
  state.prizeList.splice(4, 0, startBtn)
  console.log(state.prizeList)
})

第二步:實現(xiàn)動效

思路  跑馬燈效果的實現(xiàn)主要是轉(zhuǎn)圈高亮,這里我們可以想到當前禮物坐標和跑馬執(zhí)行步數(shù)除以8的余數(shù)一致時就高亮,但是跟禮物列表渲染的順序又不一樣,所以我們可以定義一個跑馬執(zhí)行的禮物坐標順序數(shù)組 prizeSort = [0, 1, 2, 5, 8, 7, 6, 3],這樣就是轉(zhuǎn)圈執(zhí)行啦。  然后動畫一步一步的執(zhí)行的話我們可以使用一個定時器,然后隔一點時間讓當前高亮的下標索引currentIndex變化  轉(zhuǎn)動的圈數(shù)我們可以自定義幾圈,這里我們用總執(zhí)行步數(shù)計算,必須是8的倍數(shù),比如每次要轉(zhuǎn)4圈,那基本的總執(zhí)行步數(shù)就是32步,再根據(jù)后臺中獎的禮物坐標計算出還要走多少步加上32即跑馬執(zhí)行的總部數(shù)  轉(zhuǎn)動速度的話一般是先快后忙,我們利用定時器setTimeout()方法的話第二個參數(shù)的等待時間就要越來越長,可以判斷如果執(zhí)行總步數(shù)超過一般或三分之二就開始增加定時器等待時間,讓下一步執(zhí)行越來越慢。

第三步:后臺抽獎結(jié)果

思路:  后臺返回抽獎結(jié)果的話,這里可能出現(xiàn)上面注意點問題4和5,接口報錯和長時間等待,我們處理方式可以為,點擊先請求返回結(jié)果再開始動效,對于接口報錯我們可以直接提示出來,如何長時間等待我們可以增加一個loading提示,這樣就基本可以解決這兩個問題了。對于后臺返回結(jié)果和動效執(zhí)行完結(jié)果如何匹配的問題,上面說過,我們有個基本的執(zhí)行步數(shù),然后根據(jù)請求結(jié)果的禮物坐標計算出還要走執(zhí)行多少步,相加結(jié)果就可以匹配上。

代碼

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {  margin: 0; padding: 0; box-sizing: border-box; }
    [v-cloak] {
      display: none;
    }
    .container {
      width: 450px;
      height: 450px;
      background: #98d3fc;
      border: 1px solid #98d3fc;
      margin: 100px auto;
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;
      align-items: center;
    }
    .item {
      width: 140px;
      height: 140px;
      border: 2px solid #fff;
      position: relative;
    }
    .item:nth-of-type(5) {
      cursor: pointer;
    }
    .item img {
      width: 100%;
      height: 100%;
    }
    .item p {
      width: 100%;
      height: 20px;
      background: rgba(0, 0, 0, 0.5);
      color: #fff;
      font-size: 12px;
      text-align: center;
      line-height: 20px;
      position: absolute;
      left: 0;
      bottom: 0;
    }
    .active {
      border: 2px solid red;
      box-shadow: 2px 2px 30px #fff;
    }
  </style>
</head>
<body>
  <div id="app" v-cloak>
    <div class="container">
      <div :class="['item', {'active': currentIndex === index}]"
        v-for="(item, index) in prizeList"
        @click="start(index)">
        <img :src="item.pic" alt="">
        <p v-if="index !== 4">{{ item.name }}</p>
      </div>
    </div>
  </div>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const { createApp, onMounted, ref, reactive, toRefs, computed } = Vue
    createApp({
      setup () {
        const state = reactive({
          prizeList: [
            { name: '手機', pic: 'https://bkimg.cdn.bcebos.com/pic/3801213fb80e7bec54e7d237ad7eae389b504ec23d9e' },
            { name: '手表', pic: 'https://img1.baidu.com/it/u=2631716577,1296460670&fm=253&fmt=auto&app=120&f=JPEG' },
            { name: '蘋果', pic: 'https://img2.baidu.com/it/u=2611478896,137965957&fm=253&fmt=auto&app=138&f=JPEG' },
            { name: '棒棒糖', pic: 'https://img2.baidu.com/it/u=576980037,1655121105&fm=253&fmt=auto&app=138&f=PNG' },
            { name: '娃娃', pic: 'https://img2.baidu.com/it/u=4075390137,3967712457&fm=253&fmt=auto&app=138&f=PNG' },
            { name: '木馬', pic: 'https://img1.baidu.com/it/u=2434318933,2727681086&fm=253&fmt=auto&app=120&f=JPEG' },
            { name: '德芙', pic: 'https://img0.baidu.com/it/u=1378564582,2397555841&fm=253&fmt=auto&app=120&f=JPEG' },
            { name: '玫瑰', pic: 'https://img1.baidu.com/it/u=1125656938,422247900&fm=253&fmt=auto&app=120&f=JPEG' }
          ], // 后臺配置的獎品數(shù)據(jù)
          currentIndex: 0, // 當前位置
          isRunning: false, // 是否正在抽獎
          speed: 10, // 抽獎轉(zhuǎn)動速度
          timerIns: null, // 定時器實例
          currentRunCount: 0, // 已跑次數(shù)
          totalRunCount: 32, // 總共跑動次數(shù) 8的倍數(shù)
          prizeId: 0, // 中獎id
        })
        const startBtn = { name: '開始按鈕', pic: 'https://img2.baidu.com/it/u=1497996119,382735686&fm=253' }
        // 獎品高亮順序
        const prizeSort = [0, 1, 2, 5, 8, 7, 6, 3]
        // 要執(zhí)行總步數(shù)
        const totalRunStep = computed(() => {
          return state.totalRunCount + prizeSort.indexOf(state.prizeId)
        })
        onMounted(() => {
          // state.prizeList.forEach((item, index) => {
          //  item.id = index
          // })
          state.prizeList.splice(4, 0, startBtn)
          console.log(state.prizeList)
        })
        // 獲取隨機數(shù)
        const getRandomNum = () => {
          // const num = Math.floor(Math.random() * 9)
          // if (num === 4) {
          //  console.log(">>>>>不能為4")
          //  return getRandomNum()
          // } else {
          //  return num        
          // }
          // 這里一次必然可以取到 時間為1次
          return prizeSort[Math.floor(Math.random() * prizeSort.length)]
        }
        const start = (i) => {
          if (i === 4 && !state.isRunning) {
            // 重置數(shù)據(jù)
            state.currentRunCount = 0
            state.speed = 100
            state.isRunning = true
            console.log('開始抽獎,后臺請求中獎獎品')
            // 請求返回的獎品編號 這里使用隨機數(shù) 但不能為4
            // const prizeId = getRandomNum()
            // console.log('中獎ID>>>', prizeId, state.prizeList[prizeId])
            // state.prizeId = prizeId
            // 模擬接口延時返回 如果接口突然報錯如何處理?直接調(diào)用stopRun()方法停止轉(zhuǎn)動
            setTimeout(() => {
              const prizeId = getRandomNum()
              console.log('中獎ID>>>', prizeId, state.prizeList[prizeId])
              state.prizeId = prizeId
            }, 2000)
            startRun()
          }
        }
        const startRun = () => {
          stopRun()
          console.log(state.currentRunCount, totalRunStep.value)
          // 要執(zhí)行總步數(shù)
          // 已走步數(shù)超過
          if (state.currentRunCount > totalRunStep.value) {
            state.isRunning = false
            return
          }
          state.currentIndex = prizeSort[state.currentRunCount % 8]
          // 如果當前步數(shù)超過了2/3則速度慢下來
          if (state.currentRunCount > Math.floor(state.totalRunCount * 2 / 3)) {
            state.speed = state.speed + Math.floor(state.currentRunCount / 3)
            console.log('速度>>>>', state.speed)
          }
          state.timerIns = setTimeout(() => {
            state.currentRunCount++
            startRun()
          }, state.speed)
        }
        const stopRun = () => {
          state.timerIns && clearTimeout(state.timerIns)
        }
        return {
          ...toRefs(state),
          start
        }
      }
    }).mount('#app')
  </script>
</body>
</html>

以上就是Vue3實現(xiàn)九宮格抽獎效果的示例詳解的詳細內(nèi)容,更多關(guān)于Vue3九宮格抽獎的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue-cli3.0使用及部分配置詳解

    vue-cli3.0使用及部分配置詳解

    這篇文章主要介紹了vue-cli3.0使用及部分配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • vue3使用百度地圖超詳細圖文教程

    vue3使用百度地圖超詳細圖文教程

    這篇文章主要給大家介紹了關(guān)于vue3使用百度地圖的相關(guān)資料,最近一個項目要用到地圖,因為微信小程序用的也是百度地圖,所以想著網(wǎng)頁端也用百度地圖,需要的朋友可以參考下
    2023-07-07
  • Vue3組合式API中使用forwardRef()函數(shù)

    Vue3組合式API中使用forwardRef()函數(shù)

    本文主要介紹了Vue3組合式API中使用forwardRef()函數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • 一文快速詳解前端框架 Vue 最強大的功能

    一文快速詳解前端框架 Vue 最強大的功能

    組件是 vue.js最強大的功能之一,而組件實例的作用域是相互獨立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引用。這篇文章主要介紹了一文快速詳解前端框架 Vue 最強大的功能,需要的朋友可以參考下
    2019-05-05
  • vue項目element UI input框掃碼槍掃描過快出現(xiàn)數(shù)據(jù)丟失問題及解決方案

    vue項目element UI input框掃碼槍掃描過快出現(xiàn)數(shù)據(jù)丟失問題及解決方案

    這篇文章主要介紹了vue項目element UI input框掃碼槍掃描過快出現(xiàn)數(shù)據(jù)丟失問題,輸入框要掉兩個接口,根據(jù)第一個驗證接口返回的code,彈不同的框,點擊彈框確認再掉第二個接口,需要的朋友可以參考下
    2022-12-12
  • 詳解vue-cli+element-ui樹形表格(多級表格折騰小計)

    詳解vue-cli+element-ui樹形表格(多級表格折騰小計)

    這篇文章主要介紹了vue-cli + element-ui 樹形表格(多級表格折騰小計),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • 封裝 axios+promise通用請求函數(shù)操作

    封裝 axios+promise通用請求函數(shù)操作

    這篇文章主要介紹了封裝 axios+promise通用請求函數(shù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Vue filters過濾器的使用方法

    Vue filters過濾器的使用方法

    這篇文章主要為大家詳細介紹了Vue filters過濾器的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 使用VueCli3+TypeScript+Vuex一步步構(gòu)建todoList的方法

    使用VueCli3+TypeScript+Vuex一步步構(gòu)建todoList的方法

    這篇文章主要介紹了使用VueCli3+TypeScript+Vuex一步步構(gòu)建todoList的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • vue項目如何修改title旁邊的icon圖片

    vue項目如何修改title旁邊的icon圖片

    這篇文章主要介紹了vue項目如何修改title旁邊的icon圖片,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論

肇州县| 桃江县| 黄石市| 木里| 兴安盟| 民丰县| 凤山市| 磐安县| 临沂市| 松江区| 静安区| 泰来县| 洛浦县| 和平县| 肇庆市| 绥德县| 衡南县| 姜堰市| 芷江| 堆龙德庆县| 莱芜市| 河北区| 米易县| 大关县| 崇左市| 新营市| 公安县| 澄城县| 潮安县| 西安市| 武川县| 竹溪县| 岚皋县| 中阳县| 泗水县| 荔浦县| 莎车县| 澳门| 桐柏县| 张家口市| 新丰县|