Vue3 realizes the effect of Jiugongge lottery

foreword

It’s been a long time since I wrote an article. The last time I published an article was a year-end summary. In the blink of an eye, it’s another year. Every time I want to summarize more, I can’t stick to it. It’s hard. This time, I will share a small game of Jiugongge lottery. The origin is that the company needs to do points lottery recently. I will draw a summary of the dynamic effect of the lottery, and realize the process and points of attention of a lottery function from scratch. The demo function code is implemented using vue3, which mainly uses the combined API. Since it is only a simple demo, no scaffolding and packaging tools are used.

Demand and effect

Requirements: 1. The gift is generated according to the background configuration 2. The marquee rotation effect 3. The result is generated in the background and the probability of each gift is different (the probability will not be discussed here)

Points to note: 1. How to arrange the layout, whether it is arranged according to running or from top to bottom from left to right. 2. How to insert the click button, how to generate the DOM structure 3. How to realize the effect of horse racing and how to control the speed 4. How to deal with the interface , including interface error reporting, special effects 5 when requesting Pending, background return result consistent with the selected result after the horse race, etc.

Final renderings:

Note: The pictures are all found by Baidu pictures

function realization

Step 1: Implement the layout

Idea: Request the gift list configured in the background. Generally, 8 gifts are configured, including thank you for participating. The first method is to manually layout and write 9 gift div tags. In this way, the start button can be directly written into the layout. The second one can be traversed, here I use the traverse method, but the button needs us to insert into the gift list array. The css code can use flex layout, three rows and three columns are just right, and then add the required styles. The js part mainly uses the splice() method to insert the <start button>.

Part of the code:

<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' }], // 后台配置的奖品数据
})
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)
}) 
The second step: realize the dynamic effect

The realization of the idea marquee effect is mainly to highlight in a circle. Here we can think that the current gift coordinates and the remainder of the number of steps executed by the horse race divided by 8 are the same. However, the order of rendering is different from the gift list, so we can define A sequence array of gift coordinates executed by a horse race prizeSort = [0, 1, 2, 5, 8, 7, 6, 3], so it is executed in a circle. Then, if the animation is executed step by step, we can use a timer, and then let the currently highlighted subscript index currentIndex change the number of turns at intervals. We can customize the number of turns. Here we use the total number of execution steps to calculate, which must be A multiple of 8, for example, if you need to turn 4 times each time, the basic total number of steps to execute is 32 steps, and then calculate how many steps to take based on the coordinates of the gift in the background, plus 32, which is the number of headquarters executed by the horse racing. It is fast first and then busy. If we use the timer setTimeout() method, the waiting time of the second parameter will become longer and longer. It can be judged that if the total number of execution steps exceeds normal or two-thirds, the timer waiting time will be increased. , making the execution of the next step slower and slower.

Step 3: Background lottery results

Idea: If the lottery results are returned in the background, there may be problems 4 and 5 mentioned above, such as interface error reporting and long waiting, we can handle it as follows: click to request the return result before starting the animation, and we can directly prompt out the interface error reporting , how to wait for a long time, we can add a loading prompt, so that these two problems can basically be solved. As for the question of how to match the results returned by the background with the results of the execution of the animation effect, as mentioned above, we have a basic number of execution steps, and then calculate how many steps to execute according to the gift coordinates of the request results, and add the results to match superior.

the code
<!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 <img src="https://unpkg.com/vue@3/dist/vue.global.js"></script><script> const { createApp, onMounted, ref, reactive, toRefs, computed } = VuecreateApp({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' }], // 后台配置的奖品数据currentIndex: 0, // 当前位置isRunning: false, // 是否正在抽奖speed: 10, // 抽奖转动速度timerIns: null, // 定时器实例currentRunCount: 0, // 已跑次数totalRunCount: 32, // 总共跑动次数 8的倍数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]// 要执行总步数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)})// 获取随机数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) {// 重置数据state.currentRunCount = 0state.speed = 100state.isRunning = trueconsole.log('开始抽奖,后台请求中奖奖品')// 请求返回的奖品编号 这里使用随机数 但不能为4// const prizeId = getRandomNum()// console.log('中奖ID>>>', prizeId, state.prizeList[prizeId])// state.prizeId = prizeId// 模拟接口延时返回 如果接口突然报错如何处理?直接调用stopRun()方法停止转动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)// 要执行总步数// 已走步数超过if (state.currentRunCount > totalRunStep.value) {state.isRunning = falsereturn}state.currentIndex = prizeSort[state.currentRunCount % 8]// 如果当前步数超过了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" style="margin: auto" />
</body>
</html> 

At last

Organized a set of "Interview Collection of Front-end Manufacturers", including HTML, CSS, JavaScript, HTTP, TCP protocol, browser, VUE, React, data structure and algorithm, a total of 201 interview questions, and made an answer for each question Answer and analyze.

Friends in need, you can click the card at the end of the article to receive this document and share it for free

Part of the documentation shows:



The length of the article is limited, and the following content will not be displayed one by one

Friends in need, you can click the card below to get it for free

Guess you like

Origin blog.csdn.net/web22050702/article/details/128715834