nine-grid.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <route lang="json5">
  2. {
  3. layout: 'demo',
  4. style: { navigationBarTitleText: '九宫格抽奖' },
  5. }
  6. </route>
  7. <template>
  8. <view>
  9. <view class="container">
  10. <view
  11. class="gift-item"
  12. :class="{ active: currentIndex === index }"
  13. v-for="(item, index) in prizeList"
  14. :key="index"
  15. @click="start(index)"
  16. >
  17. <image :src="item.pic" class="gift-img" />
  18. <text v-if="index !== 4" class="gift-name">{{ item.name }}</text>
  19. </view>
  20. </view>
  21. </view>
  22. </template>
  23. <script lang="ts" setup>
  24. import { ref, computed } from 'vue'
  25. const currentIndex = ref(0) // 当前位置
  26. // 后台配置的奖品数据
  27. const prizeList = [
  28. {
  29. id: 0,
  30. name: '双肩包',
  31. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/backpack.jpg',
  32. },
  33. {
  34. id: 1,
  35. name: '积木',
  36. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/jimu.jpg',
  37. },
  38. {
  39. id: 2,
  40. name: '红包',
  41. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/red-envelope.jpg',
  42. },
  43. {
  44. id: 3,
  45. name: '茶具',
  46. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/tea-set.jpg',
  47. },
  48. {
  49. id: 5,
  50. name: '可爱脸',
  51. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/tushetou.jpg',
  52. },
  53. {
  54. id: 6,
  55. name: '挖掘机',
  56. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/wajueji.jpg',
  57. },
  58. {
  59. id: 7,
  60. name: '无辜脸',
  61. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/xiaolian.jpg',
  62. },
  63. {
  64. id: 8,
  65. name: '烟灰缸',
  66. pic: 'https://cip-shopping-page-0eysug01066a9e-1302818703.tcloudbaseapp.com/fly/lottery-prize/yanhuigang.jpg',
  67. },
  68. ]
  69. const startBtn = {
  70. id: 4,
  71. name: '开始按钮',
  72. pic: 'https://img2.baidu.com/it/u=1497996119,382735686&fm=253',
  73. }
  74. // 九宫格中间位置插入开始按钮
  75. prizeList.splice(4, 0, startBtn)
  76. // 奖品高亮顺序
  77. const prizeSort = [0, 1, 2, 5, 8, 7, 6, 3]
  78. // 获取随机数
  79. const getRandomNum = () => prizeSort[Math.floor(Math.random() * prizeSort.length)]
  80. let isRunning = false // 是否正在抽奖
  81. let speed = 10 // 抽奖转动速度
  82. let timerIns = null // 定时器实例
  83. let currentRunCount = 0 // 已跑次数
  84. const totalRunCount = 32 // 总共跑动次数,8的倍数即可
  85. let prizeId = 0 // 中奖id(0-8,不能是4)
  86. // 要执行总步数
  87. const totalRunStep = computed(() => {
  88. return totalRunCount + prizeSort.indexOf(prizeId)
  89. })
  90. const stopRun = () => {
  91. // eslint-disable-next-line no-unused-expressions
  92. timerIns && clearTimeout(timerIns)
  93. }
  94. const startRun = () => {
  95. stopRun()
  96. console.log(currentRunCount, totalRunStep.value)
  97. // 要执行总步数
  98. // 已走步数超过
  99. if (currentRunCount > totalRunStep.value) {
  100. isRunning = false
  101. const prizeName = prizeList.find((e) => e.id === prizeId)!.name
  102. uni.showModal({
  103. title: `恭喜你中奖 ${prizeName}`,
  104. })
  105. return
  106. }
  107. currentIndex.value = prizeSort[currentRunCount % 8]
  108. // 如果当前步数超过了2/3则速度慢下来
  109. if (currentRunCount > Math.floor((totalRunCount * 2) / 3)) {
  110. speed += Math.floor(currentRunCount / 3)
  111. console.log('速度>>>>', speed)
  112. }
  113. timerIns = setTimeout(() => {
  114. currentRunCount++
  115. startRun()
  116. }, speed)
  117. }
  118. const start = (i) => {
  119. if (i === 4 && !isRunning) {
  120. // 重置数据
  121. currentRunCount = 0
  122. speed = 100
  123. isRunning = true
  124. console.log('开始抽奖,后台请求中奖奖品')
  125. // 请求返回的奖品编号 这里使用随机数 但不能为4
  126. // const prizeId = getRandomNum()
  127. // console.log('中奖ID>>>', prizeId, prizeList[prizeId])
  128. // prizeId = prizeId
  129. // 模拟接口延时返回 如果接口突然报错如何处理?直接调用stopRun()方法停止转动
  130. setTimeout(() => {
  131. prizeId = getRandomNum()
  132. console.log('中奖ID>>>', prizeId, prizeList[prizeId])
  133. // 拿到数据才可以跑
  134. }, 2000)
  135. startRun()
  136. }
  137. }
  138. </script>
  139. <style lang="scss">
  140. .container {
  141. display: flex;
  142. flex-wrap: wrap;
  143. align-items: center;
  144. justify-content: space-around;
  145. width: 90vw;
  146. height: 90vw;
  147. margin: 20px auto;
  148. background: #98d3fc;
  149. border: 1px solid #98d3fc;
  150. }
  151. .gift-item {
  152. position: relative;
  153. box-sizing: border-box;
  154. width: 30vw;
  155. height: 30vw;
  156. border: 2px solid #fff;
  157. }
  158. .gift-item:nth-of-type(5) {
  159. cursor: pointer;
  160. }
  161. .gift-item .gift-img {
  162. width: 100%;
  163. height: 100%;
  164. }
  165. .gift-item .gift-name {
  166. position: absolute;
  167. bottom: 0;
  168. left: 0;
  169. width: 100%;
  170. height: 20px;
  171. font-size: 12px;
  172. line-height: 20px;
  173. color: #fff;
  174. text-align: center;
  175. background: rgb(0 0 0 / 50%);
  176. }
  177. .active {
  178. border: 2px solid red;
  179. box-shadow: 2px 2px 30px #fff;
  180. }
  181. </style>