前提准备:scss 和 px2rem-loader 具体可以查看
一、新建抽奖组件 Lottery.vue
1、新components建文件夹lottery,包含src文件夹和index.js,src下面新建抽奖组件 Lottery.vue,lottery.scss
index.js
/** * {Array} prizesList : 抽奖图片数组 , 默认 [] * {Object} lotteryBtn : 抽奖按钮图片 , 默认 {img : ""} * {Number} prize : 中奖位置 , 默认 0 * {Number} speed : 速度 , 默认 100 * {Number} cycle : 转动次数 , 默认 20 * {Function} beforeLottery : 抽奖前处理函数 , 可用于发送请求获取结果 , 必须定义 * beforeLottery 需要引入两个参数 resolve 成功之后调用 , reject失败之后调用,可在reject里面写回调函数 * {Function} afterLottery : 抽奖结束回调函数 , 用于处理结果 */ export { default } from './src/Lottery.vue'
Lottery.vue
<template> <div class="iv-lottery"> <ul> <li class="row"> <div :class="['col-4' , {active : activeClass[index]}]" v-for="(item,index) in lis1" :key="index" class="prize"> <img :src="item.imgUrl"> <p class="prizeName">{{item.prizeName}}</p> </div> </li> <li class="row"> <div :class="['col-4' , {active : activeClass[7]}]" class="prize"> <img :src="lis2Img.imgUrl"> <p class="prizeName">{{lis2Img.prizeName}}</p> </div> <div class="col-4" @click="startLottery"> <div class="luck-btn"> <p class="luck-btn-txt">抽奖</p> </div> </div> <div :class="['col-4' , {active : activeClass[3]}]" class="prize"> <img :src="lis3Img.imgUrl"> <p class="prizeName">{{lis3Img.prizeName}}</p> </div> </li> <li class="row"> <div :class="['col-4' , {active : activeClass[6-index]}]" v-for="(item,index) in lis4" :key="index" class="prize"> <img :src="item.imgUrl"> <p class="prizeName">{{item.prizeName}}</p> </div> </li> </ul> </div> </template> <script type="text/javascript"> import './lottery.scss' export default { name: 'Lottery', data () { return { activeClass: [false, false, false, false, false, false, false, false], index: -1, count: 8, timer: null, times: 0, speedData: 100, afterLotteryHandler: null } }, props: { prizesList: { type: Array, default () { return [] } }, lotteryBtn: { type: Object, default () {} }, beforeLottery: { type: Function, default () { throw new Error('you must define beforeLottery before draw a lottery ') } }, afterLottery: { type: Function, // eslint-disable-next-line default () { console.warn('you can use afterLottery after rolling'); } }, prize: { type: Number, default: 0 }, speed: { type: Number, default: 100 }, cycle: { type: Number, default: 20 } }, computed: { lis1 () { let list = [] this.prizesList.forEach(item => { if ([1, 2, 3].includes(item.prizeNo)) { list.push(item) } }) // 按照奖品序号排序 list.sort((a, b) => { return a.prizeNo - b.prizeNo }) return list }, lis2Img () { let row = {} this.prizesList.forEach(item => { if (item.prizeNo === 4) { row.imgUrl = item.imgUrl row.prizeName = item.prizeName } }) return row }, lis3Img () { let row = {} this.prizesList.forEach(item => { if (item.prizeNo === 5) { row.imgUrl = item.imgUrl row.prizeName = item.prizeName } }) return row }, lis4 () { let list = [] this.prizesList.forEach(item => { if (item.prizeNo === 6) { list[0] = item } if (item.prizeNo === 7) { list[1] = item } if (item.prizeNo === 8) { list[2] = item } }) return list } }, created () { this.speedData = this.speed this.afterLotteryHandler = this.afterLottery }, beforeDestroy () { this.afterLotteryHandler = () => { } }, methods: { startLottery () { if (!this.lotteryBtn.lock) { let promise = () => { return new Promise((resolve, reject) => { this.lotteryBtn.lock = true this.beforeLottery(resolve, reject) }) } let start = async () => { try { await promise() this.roll() } catch (e) { e() } } start() } }, _rollHandler () { var index = this.index var count = this.count for (let i = 0, len = this.activeClass.length; i < len; i++) { this.activeClass[i] = false } index += 1 if (index > count - 1) { index = 0 } this.activeClass[index] = true this.index = index return false }, roll () { // eslint-disable-next-line this.activeClass = this.activeClass.map(item => item = false); this.times += 1 this._rollHandler() if (this.times > this.cycle + 10 && this.prize === this.index) { clearTimeout(this.timer) setTimeout( () => { this._showResult() } , 1000) this.lotteryBtn.lock = false this.index = -1 this.count = 8 this.timer = null this.speedData = this.speed this.times = 0 } else { if (this.times < this.cycle) { this.speedData -= 2 } else { if (this.times > this.cycle + 10 && ((this.prize === 0 && this.index === 7) || this.prize === this.index + 1)) { this.speedData += 110 } else { this.speedData += 20 } } if (this.speedData < 40) { this.speedData = 40 } this.timer = setTimeout( () => { this.roll() } , this.speedData) } return false }, _showResult () { this.afterLotteryHandler() } } } </script>
lottery.scss
.iv-lottery { ul { margin: 0 auto; padding:87px 0 0 50px; li { overflow:hidden; position: relative; margin-top:8px; } li div { width:177px; height:177px; position: relative; border-radius: 6px; float: left; margin-left:8px; text-align:center; // &.prize{ // background:#fffafa; // } &.active:before { content: ''; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 5px; background: rgba(255, 135, 46, 0.62); } } img{ width:102px; height:102px; margin-top:18px; &.img-btn{ width:209px; height:160px; position: absolute; left:50%; margin-left:-100px; // top:-10px; } } p{ &.prizeName{ color: #f15c38; font-size:22px; } &.gold{ line-height:28px; margin-top:-8px; } } .luck-btn{ margin-left:0; .luck-btn-txt{ font-size: 75px; color: #f87036; padding-top:20px; } .prizeName{ color: #d92a00; } } } }
二、引入抽奖组件
<template> <div class="lottery-module"> <p>九宫格抽奖</p> <lottery :beforeLottery="beforeLottery" :lotteryBtn="lotteryBtn" :prizesList="prizesList" :prize="prize" :afterLottery="afterLottery"></lottery> </div> </template> <script> import lottery from '@/components/lottery' export default { name: 'Lottery', components: { lottery }, data () { return { prize: 0, lotteryBtn: { img: '', lock: false }, prizesList: [ {imgUrl: require('@/assets/logo.png'), prizeNo: 1, prizeName: '1'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 2, prizeName: '2'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 3, prizeName: '3'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 4, prizeName: '4'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 5, prizeName: '5'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 6, prizeName: '6'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 7, prizeName: '7'}, {imgUrl: require('@/assets/logo.png'), prizeNo: 8, prizeName: '8'} ], count: 0 } }, mounted () { // this.getData() }, methods: { getData () { // 请求接口开始----九宫格抽奖详情 // 次数为0,抽奖按钮置灰,不能抽奖 if (this.count === 0) { this.lotteryBtn.lock = true } else { } }, beforeLottery (resolve, reject) { /* * send ajax to get result and pass to child component **/ // get result : this.prize setTimeout(() => { // 调用抽奖接口开始 ---------- console.log('抽奖开始===========') // 中奖序号 this.prize = this.lotteryPrize(2) // 抽奖开始 resolve() }, 10) }, // 抽奖九宫格抽奖位置 lotteryPrize (prizeNo) { let prize switch (prizeNo) { case 1: prize = 0 break case 2: prize = 1 break case 3: prize = 2 break case 4: prize = 7 break case 5: prize = 3 break case 6: prize = 6 break case 7: prize = 4 break default: prize = 5 } return prize }, // 抽奖结束 afterLottery () { // 抽奖结果 alert(`恭喜抽中${this.prize}`) } } } </script> <style scoped> </style>