今天来封装一个九宫格抽奖的组件 随时用随时拿。
效果图
实现原理
1.将奖品按照抽奖转动的顺序通过css去定位
2.通过索引控制一个高亮的类名,来实现跑马灯的效果
3.一般这种跑马灯转动是有速度的转变效果,先快后慢,最后停止,想要实现这个效果,我们可以在一个定时器内进行一系列的操作
上代码
这个是组件的代码 下面会有页面调用以及父子传参的介绍哦
1.html
<template>
<div class="container" :style="{width:width,height:height}">
<!-- 九宫格 -->
<div class="sudoku">
<div class="square" :style="{opacity:activatedColorIndex==0?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[0].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==1?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[1].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==2?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[2].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==7?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[7].pic" />
</div>
<div class="square" @click="clickLuck">
<img :src="lotteryButtonImage" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==3?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[3].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==6?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[6].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==5?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[5].pic" />
</div>
<div class="square" :style="{opacity:activatedColorIndex==4?'1': ( startGame ? '0.5' : '1' )}">
<img :src="prizeImages[4].pic" />
</div>
</div>
</div>
</template>
2.js
<script>
//定时器
let interval = null;
let timer = null;
//九宫格旋转速度,值越大速度越慢
let rotationalSpeed = 30;
export default {
props: {
prizeImages: { //奖品列表图片
type: Array,
},
lotteryButtonImage: { //抽奖按钮图片
type: String,
},
lotteryCount: { //抽奖次数
type: Number,
default: 0,
},
},
data() {
return {
activatedColorIndex: -1, //当前位置选中状态
btnDisabled: false,//抽奖按钮是否可以点击
startGame: false,//是否正在抽奖
};
},
methods: {
//点击抽奖按钮
clickLuck() {
let that = this;
//判断是否可以点击抽奖按钮
if (that.lotteryCount <= 0) {
mpvue.showToast({
title: '抽奖次数为0,不可抽奖!',
icon: 'none',
});
return;
}
if (this.btnDisabled) {
return;
}
this.btnDisabled = !this.btnDisabled;
this.startGame = true;
that.lotteryCount--;
interval && clearInterval(interval);
// 九宫格旋转(设置当前位置选中状态)
let index = 0;
interval = setInterval(function() {
if (index > 7) {
index = 0;
}
that.activatedColorIndex = index;
index++;
}, rotationalSpeed);
that.$emit('getlotteryPosition');
},
// 九宫格旋转减速
stop(lotteryPosition) {
let that = this;
interval && clearInterval(interval);
let currentIndex = that.activatedColorIndex + 1;
that.stopLuck(lotteryPosition, currentIndex, rotationalSpeed, 30);
},
stopLuck(lotteryPosition, currentIndex, speed, stepTime) {
let that = this;
timer && clearTimeout(timer);
timer = setTimeout(() => {
if (currentIndex > 7) {
currentIndex = 0;
}
//当前位置为选中状态
that.activatedColorIndex = currentIndex;
//如果旋转时间过短或者当前位置不等于中奖位置则递归执行直到旋转至中奖位置
if (speed < 300 || currentIndex != lotteryPosition) {
//旋转速度越来越慢
stepTime++;
speed += stepTime;
//当前位置+1
currentIndex++;
that.stopLuck(lotteryPosition, currentIndex, speed, stepTime);
}
else {
//抽奖结束
//假设中奖
setTimeout(() => {
mpvue.showModal({
title: that.prizeImages[that.activatedColorIndex].title,
content: '',
showCancel: false,
success: function(res) {
if (res.confirm) {
that.activatedColorIndex = -1;
that.btnDisabled = !that.btnDisabled;
that.startGame = false;
that.$emit('getHtml')
}
},
});
}, 500);
}
}, speed);
},
},
};
</script>
3.css
<style lang="scss" scoped>
.container {
position: relative;
margin: auto;
.sudoku {
width: 100%;
display: flex;
flex-wrap: wrap;
position: relative;
z-index: 2;
.square {
border-radius: 20px;
margin-right: 10px;
&:nth-of-type(3n-2) {
margin-left: 0 !important;
}
img {
width: 190px;
height: 190px;
}
}
.marginBottomNo {
margin-bottom: 0 !important;
}
}
}
</style>
父页面引用
为了更方便的展示,抽奖的选项我是用图片来进行一个展示,样式大家可以根据自己的设计来进行修改,数据格式也可按照后台返回的进行调整。
<template>
<div class="wrap wrap-prize">
<div class="luck-draw">
<luck-draw ref="lottery" @getHtml="getHtml" @getlotteryPosition="getlotteryPosition" :lotteryCount="lotteryCount"
:prizeImages="prize" :lotteryButtonImage="lotteryButtonImage"></luck-draw>
</div>
</div>
</template>
<script>
import luckDraw from '@/components/luckDraw';
export default {
components: {
luckDraw,
},
data() {
return {
prize: [],
lotteryCount: 100,//抽奖次数
lotteryButtonImage: '/static/imgs/prize_chou.png',//抽奖按钮图片
};
},
methods: {
toUrl(url) {
nav.goPage({url});
},
getHtml() { //请求数据后台返回的抽奖选项
this.prize = [
{
'title': '1元现金',
'amount': 1,
'pic': 'https://s1.dgbg114.com/upfiles/1591951960179.png',
},
{
'title': '50元现金',
'amount': 50,
'pic': 'https://s1.dgbg114.com/upfiles/1591951967858.png',
},
{
'title': '2元现金',
'amount': 2,
'pic': 'https://s1.dgbg114.com/upfiles/1591951970260.png',
},
{
'title': '5元现金',
'amount': 5,
'pic': 'https://s1.dgbg114.com/upfiles/1591951973393.png',
},
{
'title': '谢谢参与',
'amount': 0,
'pic': 'https://s1.dgbg114.com/upfiles/1591952011096.png',
},
{
'title': '100元现金',
'amount': 100,
'pic': 'https://s1.dgbg114.com/upfiles/1591952019990.png',
},
{
'title': '10元现金',
'amount': 10,
'pic': 'https://s1.dgbg114.com/upfiles/1591952035647.png',
},
{
'title': '谢谢参与',
'amount': 0,
'pic': 'https://s1.dgbg114.com/upfiles/1591952044865.png',
},
];
},
getlotteryPosition() {
let that = this;
let num = Math.ceil(Math.random() * 7);
//模拟网络请求时间
setTimeout(() => {
that.$refs.lottery.stop(num);
}, 3000);
},
},
onShow() {
this.getHtml()
},
};
</script>
<style lang="scss">
.wrap-prize {
.luck-draw{
padding: 40% 75px 0 75px;
display: block;
margin: 0 auto;
}
}
</style>
以上就是所有的代码,可以根据自己的需求去进行调整。
下面给大家总结一下核心代码
1.核心代码就是stopLuck函数,整个函数在一个定时器中,通过activatedColorIndex 索引值变化,实现转动效果
2.由于每次只跳动一步,需要在stop函数中调用stopLuck函数,达到连续跑动效果
3.当满足时间 && 后台返回中奖值时或者抽中奖品值匹配时,清除定时器,弹出中奖内容
4.加减速是通过speed值控制的,同时他也是定时器中设置的 等待的时间值,值越大,等待越久,就越慢;反之越快