Written in front
I changed my career in the middle and bumped into the front end by mistake. It may be due to my 'laziness'. I have never published technical articles or development experience, and I am deeply ashamed. Therefore, I have changed my mind and decided to share something.
This article only describes the tip of the iceberg, welcome to leave a message of valuable experience ~.
1. demand
Page belongs to active page
a. enter the page and request the background interface to pull the remaining times of the current user's Lottery
b. click the start button of the nine palace grid to start turning and request the backstage interface
c. the interface request is successful, and the rotation stops according to the dwell position returned by the interface
The general effect is as follows
2. Component source code
template section
<template> <div> <ul> <li :class="['item' + index, {'active': item.active}]" :key="index" v-for="(item, index) in list"> <img :src="item.img" :alt="item.info" /> <span>{}</span> <span></span> </li> <li @click="move"> <span>Button</span> <i></i> </li> </ul> <div> <span>You have{}Chance to draw</span> </div> </div> </template>
Part script
<script> import { post } from '@common/js/ajax'; import { deepQuery } from '@mfw/trans-core'; export default { data() { return { // Award list list: [ { img: 'https://N3-q.mafengwo.net/s12/m00/43/1c/wkged1v_yumqapeuxaabg61crqek46. JPEG ', info:' thank you for your participation ', active: false}, { img: 'https://B1-q.mafengwo.net/s12/m00/43/1c/wkged1v \, { img: 'https://N3-q.mafengwo.net/s12/m00/42/2c/wkged1v \, { img: 'https://N3-q.mafengwo.net/s12/m00/43/1c/wkged1v_yumqapeuxaabg61crqek46. JPEG ', info:' ma cellular passport package ', active: false}, { img: 'https://B1-q.mafengwo.net/s12/m00/43/1c/wkged1v 65123; mqatfwoaa8r6he ﹣ a471. JPEG ', info:' thank you for your participation ', active: false}, { img: 'https://N3-q.mafengwo.net/s12/m00/42/2c/wkged1v \, { img: 'https://B1-q.mafengwo.net/s12/m00/43/1c/wkged1v ﹣ mqatfwoaa8r6he ﹣ a471. JPEG ', info:' mafengwo suitcase ', active: false}, { img: 'https://N3-q.mafengwo.net/s12/m00/42/2c/wkged1v ﹣ ayagknkaaa33 ﹣ key444. JPEG ', info:' ma cellular calendar ', active: false}, ], // Last stop index lastIndex: 0, // Server back to stay index stopIndex: 0, // Normal rotation animation timer1: null, // Enter slow rotation animation timer2: null, // Slow rotation animation timer3: null, // Executing animation isMoving: false, // Turn for a minimum of 12 times (one and a half turns) to prevent the turning time from being too short times: 0, // Interface successfully returned stop stopIndex identity ajaxEnd: false, // Enter slow rotation animation logo timerEnd: false, // Number of user lottery (actually it should be the number of backstage returns) luckyTimes: 5, }; }, watch: { times(val) { // If ajax fails during the count if (!this.ajaxEnd) { return false; } if (val >= 12) { this.timerEnd = true; } }, }, methods: { getStopIndex() { // Get the index returned by the server post('/lottery') .then((res) => { if (deepQuery(res, 'data', 'success')) { this.stopIndex = deepQuery(res, 'data', 'data'); if (this.lastIndex !== this.stopIndex || this.lastIndex === this.stopIndex) { this.ajaxEnd = true; } } else { return Promise.reject(deepQuery(res, 'data', 'message')); } }) .catch((err) => { // Initialization data clearInterval(this.timer1); this.list.map((e) => { e.active = false; }); this.lastIndex = 0; this.isMoving = false; this.lastIndex = 0; this.times = 0; const errMsg = typeof err === 'string' ? err : 'The server is busy, please try again later'; this.showToast(errMsg); }); }, move() { // Click the start game button if (!this.luckyTimes) { console.error('No more sweepstakes'); return false; } if (this.isMoving) { return false; } this.isMoving = true; this.ajaxEnd = false; this.timerEnd = false; this.times = 0; console.error('Last stop position: ', this.lastIndex); let i = this.lastIndex; // Execute ajax request data this.getStopIndex(); // Execution animation this.timer1 = setInterval(() => { this.times++; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); // When the server data index is obtained if (this.timerEnd) { console.log('Stop location returned by server: ', this.stopIndex); clearInterval(this.timer1); this.enter(i, this.stopIndex); } }, 100); }, enter(cur, stop) { // Calculate the index to stop console.log(cur, stop); let count = stop - cur; if (count <= 4) { count = count > -4 ? count + 8 : count + 16; } let i = cur; this.timer2 = setInterval(() => { count--; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); if (count === 4) { clearInterval(this.timer2); this.stop(i, stop); } }, 100); }, stop(cur, stop) { // Calculate the index to stop let count = 0; let i = cur; this.timer3 = setInterval(() => { count++; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); if (count === 4) { clearInterval(this.timer3); this.isMoving = false; this.lastIndex = this.stopIndex; this.luckyTimes--; } }, 300); }, showToast(err) { // toast prompt alert(err); }, }, beforeDestroy() { // Before component destruction // Clear timer clearInterval(this.timer1); clearInterval(this.timer2); clearInterval(this.timer3); }, }; </script>
Part style
<style lang="scss"> .v-common-com-lottery { height: 100%; font-size: .24rem; color: #fff; .list { position: relative; background: lightblue; width: 100%; padding-bottom: 100%; } .item { width: 32%; padding-bottom: 32%; position: absolute; background: lightgreen; border-radius: .24rem; overflow: hidden; &.item0 { left: 0; top: 0; } &.item1 { left: 34%; top: 0; } &.item2 { left: 68%; top: 0; } &.item3 { left: 68%; top: 34%; } &.item4 { left: 68%; top: 68%; } &.item5 { left: 34%; top: 68%; } &.item6 { left: 0; top: 68%; } &.item7 { left: 0; top: 34%; } .icon { position: absolute; height: 100%; width: 100%; z-index: 1; } .info { position: absolute; left: 0; bottom: 0; background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .5)); height: .48rem; width: 100%; z-index: 2; display: flex; align-items: center; justify-content: center; } .mask { position: absolute; left: 0; top: 0; z-index: 3; width: 100%; height: 100%; background: rgba(0, 0, 0, .4); opacity: 0; } &.active .mask{ opacity: 1; } } .btn { width: 32%; padding-bottom: 32%; background: lightsalmon; position: absolute; left: 34%; top: 34%; font-size: .72rem; border-radius: .24rem; overflow: hidden; .text { position: absolute; height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; z-index: 2; } .mask { position: absolute; height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; z-index: 2; } } .lucky-times { color: #000; font-size: .36rem; } } </style>
@common/js/ajax source code is as follows
// https://github.com/axios/axios const axios = require('axios'); // Timeout 15 seconds // axios.defaults.timeout = 15000; // Allow cookie s to be sent axios.defaults.withCredentials = true; /** * get request * @param url - Requested path * @param params - parameter * @return */ export function get(url, params = {}) { return axios.get(url, { params, }); } /** * post request * @param url - Requested path * @param data - parameter * @param config - original configuration * @return */ export function post(url, data = {}, config = {}) { return axios.post(url, data, config); }
The source code of deepQuery is as follows
/** * Deep query ({}, "a", "B", "C") * @param func Objects to query * @return true or false */ export function deepQuery(obj, ...args) { return args.reduce((a, b) => (a ? a[b] : a), obj); }