uni-app 老虎机功能
- 该老虎机抽奖功能兼容 小程序/APP/H5,主要通过
swiper内置组件实现
组件配置
- 子组件
<!-- m-slotMachine-item.vue -->
<template>
<view class="draw-swiper-wrap">
<swiper class="draw-swiper" skip-hidden-item-layout circular disable-touch acceleration :indicator-dots="false"
:vertical="true" :display-multiple-items="1" :current="currentIndex" :autoplay="isAutoplay"
:interval="interval" :duration="duration" @change="onChange">
<swiper-item v-for="(item, index) in prizeArr" :key="index">
<image class="draw-prize-img" mode="aspectFill" :src="item.img"></image>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
props: {
index: { // 结果下标
type: Number,
default: 0
},
prizeArr: { // 奖品数组
type: Array,
default: () => {
return [];
}
},
interval: { // 自动切换时间间隔
type: Number,
default: 0
},
duration: { // 滑动动画时长
type: Number,
default: 0
},
},
data() {
return {
isAutoplay: false, // 是否开始抽奖 (自动播放)
currentIndex: 0, // swiper对应的index
}
},
methods: {
onChange(event) {
if (this.index === event.detail.current) {
this.isAutoplay = false;
// 抽奖结束
setTimeout(() => {
this.$emit("drawStop")
}, 500)
}
},
//触发滚动
startScroll() {
this.isAutoplay = true;
}
},
}
</script>
<style lang="scss" scoped>
.draw-swiper-wrap {
width: 100%;
height: 100%;
display: flex;
align-items: center;
flex: 1;
.draw-swiper {
width: 100%;
height: 100%;
}
.draw-prize-img {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
}
</style>
- 父组件
<!-- m-slotMachine.vue -->
<template>
<view class="m-slotMachine-wrap">
<view class="m-slotMachine">
<m-slot-machine-item :ref="`slotMachine${index}`" :interval="50" :duration="100" :prizeArr="prizeArr"
:index="results[index]" v-for="(item, index) in column" :key="index" @drawStop="stop(index)" />
</view>
</view>
</template>
<script>
import mSlotMachineItem from './m-slotMachine-item.vue';
export default {
components: {
mSlotMachineItem
},
props: {
// 抽奖秒数
seconds: {
type: Number,
default: 3
},
// 每个奖池滚动间隔
interval: {
type: Number,
default: 200
},
// 奖池
prizeArr: {
type: Array,
default: () => {
// 数组内容解析,奖池图片的默认尺寸为 80 * 120
// {
// name: '奖品 名称'
// value: '奖品 ID'
// img: '图片 url 地址'
// }
return []
}
},
// 抽奖列数
column: {
type: Number,
default: 3
}
},
data() {
return {
luckyDrawLoading: false, // 抽奖中
results: [-1,-1,-1], // 开奖结果
}
},
watch: {
prizeArr(newVal) {
// 初始化随机
this.$nextTick(() => {
this.results = this.getResults()
})
}
},
methods: {
// 开始抽奖
start(id = undefined) {
if (this.luckyDrawLoading) {
return;
}
// 防止重复点击
this.luckyDrawLoading = true;
// 初始化结果
this.results = [-1,-1,-1]
this.results.forEach((item, index) => {
// 开始滚动
setTimeout(() => {
this.$refs[`slotMachine${index}`][0].startScroll();
}, (index * interval));
})
let {
interval,
seconds
} = this
let getArr = this.getResults(id)
this.results.forEach((item, index) => {
// 开始滚动
setTimeout(() => {
this.$set(this.results, index, getArr[index])
}, (seconds * 1000) + (index * interval));
})
},
// 抽奖结束
stop(index) {
if(index !== this.results.length - 1) {
return
}
this.luckyDrawLoading = false;
this.$emit('drawEnd')
},
// 获取结果 or 随机
getRandom(arr = []) {
let max = this.prizeArr.length - 1;
let index = Math.floor(Math.random() * (max - 1 + 1) + 1)
if (!arr.includes(index)) {
return index
} else {
return this.getRandom(arr)
}
},
// 获取中奖结果下标数组
getRandomArr(id = undefined) {
let results = [];
for(let i = 0;i < this.column;i++) {
results.push(
id ?
this.prizeArr.findIndex(item => item.value === id) :
this.getRandom(results)
)
}
return results
},
// 获取中奖结果
getResults(id = undefined) {
if(!this.prizeArr.length){
return uni.showToast({
title: '奖池不能为空',
duration: 2000,
icon: 'none'
});
}
// id 为中奖
let arr = this.getRandomArr(id);
return arr
},
},
}
</script>
<style lang="scss" scoped>
.m-slotMachine-wrap{
width: 558rpx;
height: 280rpx;
.m-slotMachine {
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
&::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
z-index: 6;
content: '';
}
}
}
</style>
使用
<template>
<view>
<view class="draw_wrap">
<m-slotMachine ref="draw" :prizeArr="prizeArr" @drawEnd="end"/>
</view>
<button @click="drawClick()">抽奖</button>
</view>
</template>
<script>
import mSlotMachine from "@/components/m-slotMachine/m-slotMachine.vue";
export default {
components: {
mSlotMachine
},
data() {
return {
prizeArr: [],
}
},
onLoad() {
this.init()
},
methods: {
init() {
// 初始化获取奖池信息
this.prizeArr = [
{
name: 'iPhone13',
value: 'iPhone',
img: require('@/xxx.png')
},
{
name: 'airPods3',
value: 'airPods',
img: require('@/xxx.png')
},
{
name: '行李箱',
value: 'luggage',
img: require('@/xxx.png')
},
{
name: '风筒',
value: 'dryer',
img: require('@/xxx.png')
},
{
name: '平行车',
value: 'balanceCar',
img: require('@/xxx.png')
},
{
name: 'iPad5',
value: 'iPad',
img: require('@/xxx.png')
}
]
},
drawClick(){
// 模拟抽奖结果,随机一个奖品,实际可根据后端返回的奖品 ID 进行配置
let id = this.$refs.draw.prizeArr[this.$refs.draw.getRandom()].value
this.$refs.draw.start(id);
},
end() {
console.log('抽奖结束')
}
},
}
</script>
<style lang="scss" scoped>
page {
background: #fff;
padding: 0 20rpx;
}
.draw_wrap{
display: flex;
justify-content: center;
padding: 80rpx 0;
::v-deep{
.draw-swiper-wrap{
width: 160rpx;
height: 240rpx;
border-radius: 10rpx;
border: 2rpx solid #d2d2d2;
overflow: hidden;
& + .draw-swiper-wrap{
margin-left: 20rpx;
}
}
}
}
</style>
Powered by Waline v2.15.8