功能介绍
因为是移动端转盘抽奖所以使用了upx单位。
- 支持展示文字
- 支持显示图片
- 支持后端指定抽奖结果
- 可自定义轮盘宽度,背景颜色,按钮/指针图片
效果展示
源码
<template>
<view class="page">
<view class="Alottery">
<view class="AlotteryMain">
<view class="graph-page">
<view class="plate-wrapper" :style="`${bgColor};`">
<view class="item-plate" :style="plateCss(index)" v-for="(item, index) in plateList" :key="index">
<p>{{ item.prizeName }}</p>
<img :src="item.prizeImg" alt="" />
</view>
</view>
<view @click="extract" class="btn"></view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
plateList: [], //奖品列表
isRunning: false, //判断是否正在转动
rotateAngle: 0, //转盘每项角度
baseRunAngle: 360 * 5, //总共转动角度,至少5圈
totalRunAngle: 0, //要旋转的总角度
activeIndex: 0, //中奖index
wrapDom: null //转盘dom
};
},
computed: {
bgColor() {
//转盘的每项背景
let len = this.plateList.length;
let color = ['#fda403', '#f33535'];
let colorVal = '';
this.plateList &&
this.plateList.forEach((item, index) => {
colorVal += `${color[index % 2]} ${(360 / len) * index}deg ${(360 / len) * (index + 1)}deg,`;
});
return `background: conic-gradient(${colorVal.slice(0, -1)})`;
},
plateCss() {
//转盘的每项样式
if (this.plateList && this.plateList.length) {
return i => {
return `
width: ${Math.floor(2 * 485 * Math.sin(((this.rotateAngle / 2) * Math.PI) / 180))}upx;
height: 600upx;
transform: rotate(${this.rotateAngle * i + this.rotateAngle / 2}deg);
transform-origin: 50% 100%;
`;
};
}
return () => {
'';
};
}
},
created() {
this.getPrizeList(); // 模拟请求奖品列表接口
},
mounted() {
this.$nextTick(() => {
this.wrapDom = document.getElementsByClassName('plate-wrapper')[0];
});
},
beforeDestroy() {
this.wrapDom.removeEventListener('transitionend', this.stopRun);
},
methods: {
// 模拟获取奖品列表接口
getPrizeList() {
let testing = [
{
id: '1',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖1'
},
{
id: '2',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖2'
},
{
id: '3',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖3'
},
{
id: '4',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖4'
},
{
id: '5',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖5'
},
{
id: '6',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖6'
},
{
id: '7',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖7'
},
{
id: '8',
prizeImg: 'https://img.ixintu.com/upload/jpg/20210612/4bd6a895253f0fd0dea87a3db22ccb9f_177837_800_1640.jpg!con0',
prizeName: '棒棒糖8'
}
];
this.plateList = testing;//奖品赋值
// 根据奖品数量绘制扇形
this.rotateAngle = 360 / this.plateList.length;
this.totalRunAngle = this.baseRunAngle + 360 - this.activeIndex * this.rotateAngle - this.rotateAngle / 2;
},
// 1点击抽奖按钮
extract() {
if (this.isRunning) return;
this.isRunning = true;
this.drawFu();
},
// 2抽奖
drawFu() {
this.activeIndex = 1; //控制抽奖奖品下标
this.rotateAngle = 360 / this.plateList.length;
this.totalRunAngle = this.baseRunAngle + 360 - this.activeIndex * this.rotateAngle - this.rotateAngle / 2;
this.startRun();
},
// 3转动
startRun() {
this.wrapDom.setAttribute(
'style',
`
${this.bgColor};
transform: rotate(${this.totalRunAngle}deg);
transition: all 4s ease;
`
);
this.wrapDom.addEventListener('transitionend', this.stopRun); // 监听transition动画停止事件
},
// 4抽奖停止
stopRun() {
this.isRunning = false;
this.wrapDom.setAttribute(
'style',
`
${this.bgColor};
transform: rotate(${this.totalRunAngle - this.baseRunAngle}deg);
`
);
}
}
};
</script>
<style lang="scss" scoped>
.page {
width: 100vw;
height: 100vh;
background-color: #fff;
display: flex;
justify-content: center;
/* 圆盘 */
.Alottery {
width: 630upx;
height: 630upx;
background-color: #f9d76c;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.title {
text-align: center;
color: #fff;
font-size: 32px;
line-height: 4rem;
}
.AlotteryMain {
width: 100%;
height: 600upx;
display: flex;
justify-content: center;
align-items: center;
.graph-page {
width: 1200upx;
height: 1200upx;
transform: scale(0.5);
}
.plate-wrapper {
width: 1200upx;
height: 1200upx;
border-radius: 50%;
}
.item-plate {
margin: auto;
box-sizing: border-box;
position: absolute;
top: 0upx;
left: 0upx;
right: 0upx;
}
.item-plate img {
width: 135upx;
height: 135upx;
margin-top: 30upx;
margin: auto;
display: block;
padding: 10upx;
box-sizing: border-box;
}
.item-plate p {
width: 100%;
height: 75upx;
color: #fff;
font-size: 22px;
text-align: center;
line-height: 22px;
margin-top: 60upx;
padding: 0 20upx;
box-sizing: border-box;
}
.btn {
width: 160px;
height: 160px;
background: url('https://www.jq22.com/demo/jquerylocal201912122316/img/btn_lottery.png') no-repeat center / 100% 100%;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
cursor: pointer;
}
.btn::before {
content: '';
width: 41px;
height: 39px;
background: url('https://www.jq22.com/demo/jquerylocal201912122316/img/icon_point.png') no-repeat center / 100% 100%;
position: absolute;
left: 0;
right: 0;
top: -33px;
margin: auto;
}
}
}
}
</style>