最近公司要做一个抽奖的活动。由于时间关系我使用的是同事的组件。但是活动过后心里难免心生内疚,毕竟如果老是使用别人封装好的东西也挺不好意思的。所以我打算自己封装一个抽奖的组件Demo来为我以后写这类活动提供思路。
话不多说,直接上代码吧。
lottory.vue
<template>
<div class="lottory">
<div class="lottory-wrap relative">
<div v-for="(item,index) in items" :key="index" class="lottory-item absolute" :class="item.isActive ? 'isActive' : ''" :style="item.position">{{item.id}}</div>
<div class="lottory-btn absolute" @click="onStartLottory(steps)">抽奖</div>
</div>
</div>
</template>
<script>
let $activeIndex = 0 //记录当前轮盘停留的位置
let $count = 0 // 定义一个变量来判断是否走完了传入的步数
let $lottorying = false // 定义这个变量判断是否还在抽奖中以防止多次点击
export default {
name: 'lottory',
props: {
items: {
type: Array,
default: () => []
},
steps: {
type: Number,
default: () => 0
}
},
methods: {
onStartLottory(steps) {
if(!steps) {
return
}
if($lottorying) {
console.log('正在抽奖')
return
}
$lottorying = true
const timer = setInterval(() => {
if($activeIndex === 8) {
$activeIndex = 0
}
this.items.forEach((item, index) => {
if($activeIndex === index) {
this.$set(item, 'isActive', true)
} else {
this.$set(item, 'isActive', false)
}
})
if($count === steps) {
$count = 0
$lottorying = false
clearInterval(timer)
return
}
$activeIndex++
$count++
}, 100)
}
}
}
</script>
<style>
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.lottory-item {
width: 50px;
height: 50px;
background: red;
line-height: 50px;
text-align: center;
color: #fff;
}
.lottory-btn {
width: 50px;
height: 50px;
left: 60px;
top: 60px;
background: blue;
color: #fff;
font-weight: 600;
font-size: 20px;
text-align: center;
line-height: 50px;
}
.isActive{
background: #39b89c;
}
</style>
app.vue
<template>
<div id="app">
<lottory :items.sync="items" :steps="steps" ref="my-lottory"></lottory>
<div class="start-btn" @click="start(10)"></div>
</div>
</template>
<script>
import lottory from './components/lottory.vue'
export default {
name: 'App',
components: {
lottory
},
data() {
return {
items : [
{id:1, position: {}},
{id:2, position: {left:'60px',top:'0'}},
{id:3, position: {left:'120px', top:'0'}},
{id:4, position: {left:'120px',top:'60px'}},
{id:5, position: {left:'120px',top:'120px'}},
{id:6, position: {left:'60px',top:'120px'}},
{id:7, position: {left:'0',top:'120px'}},
{id:8, position: {left:'0',top:'60px'}}
],
steps: 0
}
},
methods: {
start(steps) {
this.$refs['my-lottory'].onStartLottory(steps)
}
}
}
</script>
<style>
.start-btn{
position: absolute;
width: 50px;
height: 50px;
top: 67px;
left: 67px;
}
</style>
最后的效果图
之后的一些改进的想法
公司做的活动大部分都是需要贴图的,然而我做的这个组件只是将功能实现了,然后样式方面没有做很好的封装。后续我会尝试将暂时写死的样式换成可传入图片的形式。