nine-grid.vue 4.8 KB

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