写一个用于抽奖的转盘的vue文件
时间: 2024-05-27 16:15:02 浏览: 15
<template>
<div class="roulette">
<div class="plate" :style="{transform: 'rotate('+ rotateAngle + 'deg)'}">
<div class="sector" v-for="(item, index) in items" :key="index"
:style="{transform: 'rotate('+ (index * sectorAngle) + 'deg) skewY('+ skewAngle +'deg)'}"
:class="'sector-' + (index + 1)">
<span>{{ item }}</span>
</div>
</div>
<div class="center"></div>
<button class="btn" @click="start">Start</button>
</div>
</template>
<script>
export default {
name: 'Roulette',
props: {
items: {
type: Array,
required: true
},
duration: {
type: Number,
default: 5000
},
minSpins: {
type: Number,
default: 2
},
maxSpins: {
type: Number,
default: 5
}
},
data() {
return {
sectorAngle: 0,
skewAngle: 0,
rotateAngle: 0,
spinning: false,
spinCount: 0,
winner: null
}
},
computed: {
plateStyle() {
return {
transform: `rotate(${this.rotateAngle}deg)`
}
}
},
mounted() {
this.sectorAngle = 360 / this.items.length;
this.skewAngle = Math.atan(Math.tan((Math.PI / this.items.length) / 2)) * (180 / Math.PI);
},
methods: {
start() {
if (this.spinning) {
return;
}
this.spinning = true;
this.spinCount = 0;
this.winner = null;
this.rotateAngle = this.getRandomRotation();
this.animate();
},
getRandomRotation() {
const min = Math.ceil(0);
const max = Math.floor(360);
return Math.floor(Math.random() * (max - min + 1)) + min;
},
animate() {
this.rotateAngle += 360;
this.spinCount++;
if (this.spinCount >= this.minSpins && this.winner === null) {
this.winner = this.items[Math.floor(Math.random() * this.items.length)];
}
if (this.spinCount <= this.maxSpins || this.winner === null) {
setTimeout(() => {
this.animate();
}, this.duration);
} else {
this.spinning = false;
}
}
}
}
</script>
<style scoped>
.roulette {
position: relative;
}
.plate {
position: relative;
width: 300px;
height: 300px;
margin: 0 auto;
border-radius: 50%;
border: 2px solid #333;
transform-style: preserve-3d;
transition: transform 5s ease-out;
}
.sector {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform-origin: 0 0;
overflow: hidden;
}
.sector span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) skewY(-{{skewAngle}}deg);
font-size: 16px;
font-weight: bold;
text-align: center;
white-space: nowrap;
}
.center {
position: absolute;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
margin: -25px 0 0 -25px;
border-radius: 50%;
background-color: #333;
}
.btn {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
padding: 10px 20px;
font-size: 16px;
font-weight: bold;
background-color: #333;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)