转盘抽奖
- 最近接了个需求实现转盘抽奖活动, 所以就先写了个demo先发出来记录一下
- 点击开始旋转的按钮是图片
- 因为奖品是后台配置,所以每一个扇叶(奖品选项)是代码计算出来写的
- 项目使用vue框架,所以是vue语法
- 单独封装了game.js, 需要引入到组件
效果
choujiang
开始旋转按钮图片资源
game.js
// 游戏
const game = {
turntable: null, // 盘子
angle: 0, // 旋转角度
lastAngle: 0, // 上次旋转角度
transitionTime: 6, // 过渡时间 默认6秒
init(turntable) {
this.turntable = turntable
this.turntable.style.transition = `all ${this.transitionTime}s`
},
rotate(angle, callback) {
const defaultAngle = 3600 // 默认先转6圈
this.angle += defaultAngle + angle - this.lastAngle
this.lastAngle = angle
console.log(this.angle, '旋转的角度');
this.turntable.style.transform = `rotate(${this.angle}deg)`
setTimeout(() => {
callback()
}, this.transitionTime * 1000)
}
}
export default game
整个组件代码
<template>
<div class="home">
<div class="container">
<div class="content" id="luckyDraw">
<div class="flabellum" v-for="(item, index) in dataList" :key="index">
{{ item.name }}
</div>
</div>
<!-- 开始按钮 -->
<img
class="arrow"
@click="handlerStartGame"
src="../assets/img/1.png"
id="startBtn"
alt=""
/>
</div>
</div>
</template>
<script>
import game from "../utils/game";
export default {
components: {},
data() {
return {
dataList: [
{
name: "运动",
},
{
name: "学习",
},
{
name: "休息",
},
{
name: "喝奶茶",
},
{
name: "看书",
},
{
name: "赛车",
},
{
name: "吃鸡",
},
{
name: "王者",
},
],
isRotate: true, // 是否可以点击按钮开始抽奖
};
},
computed: {},
mounted() {
// 页面加载后再执行游戏相关操作
window.onload = () => {
const luckyDraw = document.getElementById("luckyDraw");
const startBtn = document.getElementById("startBtn");
// 初始化游戏
game.init(luckyDraw);
// 绑定开始抽奖按钮点击事件
startBtn.onclick = this.startGame;
};
this.setBladeWidth();
this.settingDataItemRotate();
},
methods: {
// 动态计算每一扇叶元素宽度
setBladeWidth() {
let $ = function (selector) {
return document.querySelectorAll(selector);
};
let num = this.dataList.length;
//diameter转盘直径(根据自己测量直径填入就好);width扇叶元素宽度;deg每一叶的旋转角度
let diameter = 300,
width = 0,
deg = 360 / num;
width = diameter * Math.tan(((deg / 2) * Math.PI) / 180);
$(".flabellum").forEach((e, ind) => {
// 动态初始化每一扇叶的宽度
e.style.width = width + "px";
// 动态初始化每一扇叶该旋转的角度
e.style.transform = `rotateZ(${ind * (360 / this.dataList.length)}deg)`;
});
},
// 动态计算出当前数组每一项应该旋转的角度并传入数组每一项obj作为key
settingDataItemRotate() {
// 设置dataList中的rotate
const value = 360 / this.dataList.length;
let arr = JSON.parse(JSON.stringify(this.dataList)).reverse();
arr.forEach((ele, ind) => {
arr[ind].rotate = value * (ind + 1);
if (ind == arr.length - 1) arr[ind].rotate = 0;
});
this.dataList = JSON.parse(JSON.stringify(arr)).reverse();
},
handlerStartGame() {
if (!this.isRotate) return;
this.isRotate = false;
// 产生随机数,获得随机抽奖结果
const num = Math.floor(Math.random() * this.dataList.length);
// 启动旋转
game.rotate(this.dataList[num].rotate, () => {
// 动画结束,展示结果
alert(`恭喜你获得-${this.dataList[num].name}`);
this.isRotate = true;
});
},
},
};
</script>
<style lang="scss" scoped>
.container {
position: relative;
width: 300px;
height: 300px;
border-radius: 50%;
background: #f7c894;
display: flex;
justify-content: center;
overflow: hidden;
border: 20px solid #ffbd72;
}
.content {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
border-radius: 50%;
overflow: hidden;
}
.flabellum {
position: absolute;
width: 100px;
height: 50%;
clip-path: polygon(50% 100%, 0% 0%, 100% 0%);
-webkit-clip-path: -webkit-polygon(50% 100%, 0% 0%, 100% 0%);
transform-origin: 50% 100%;
text-align: center;
color: #000;
font-size: 30px;
}
.container .flabellum:nth-child(odd) {
background-color: #f7c894;
}
.container .flabellum:nth-child(even) {
background-color: red;
}
.arrow {
width: 60px;
height: 80px;
position: absolute;
left: 50%;
top: 50%;
z-index: 999;
transform: translateX(-50%);
transform: translate(-50%, -50%);
}
</style>