// 这是组件Wheel.vue
<template>
<view
class="wheel-container"
:style="{ width: width + 'px', height: width + 'px' }"
>
<view
class="wheel-list"
:style="{
backgroundImage: 'url(' + bgImg + ')',
transform: `rotate({degValue || initDeg}deg)`,
}"
>
<view v-for="(item, index) in prizeList" :key="index">
<!-- {{item}} -->
<view class="wheel-item">
<view
class="wheel-img"
:style="{
width: prizeWidth,
paddingTop: prizePaddingTop,
transform: `rotate({index * (360 / prizeList.length)}deg)`,
'transform-origin': itemTransformOrigin,
}"
>
<!-- <image :src="item.img" mode="widthFix" style="height:auto" /> -->
<!-- <view class="wheel_num" v-if="item.num">
{{item.num}}
</view> -->
<view class="wheel_name">
<view class="" style="font-weight: bold; font-size: 16px">
{{ item.title[0] || "" }}
</view>
<view class="">
{{ item.title[1] || "" }}
</view>
</view>
</view>
</view>
</view>
</view>
<view class="wheel-btn">
<image :src="btnImg" mode="widthFix" class="img" @click="start" />
</view>
</view>
</template>
<script>
export default {
name: "Wheel",
data() {
return {
// degValue: 0, // 旋转角度
// prizeWidth: 0, // 奖项背景图宽度计算值
// prizePaddingTop: 0, // 奖项上边距计算值
// itemTransformOrigin: '', // 奖项旋转原点计算值
degValue: 0,
itemTransformOrigin: "",
prizeWidth: NaN,
prizePaddingTop: NaN,
count: 6,
rotNum: 0,
onRunning: false,
};
},
props: {
width: {
type: Number,
default: 312,
}, // 画布大小,默认单位 rpx
initDeg: {
type: Number,
default: 0,
}, // 初始旋转角度
rotTimes: {
type: Number,
default: 1,
}, // 抽奖机会次数
prizeList: {
type: Array,
default: () => {},
}, // 奖品列表
prizeName: {
type: String,
default: "",
}, // 获奖项名字
// prizeWidth: {
// type: Number,
// default: NaN
// }, // 奖项宽度
// prizePaddingTop: {
// type: Number,
// default: NaN
// }, // 奖项距离圆弧的内边距
bgImg: {
type: String,
default: "/static/wheel_bg.png",
}, // 背景图
btnImg: {
type: String,
default: "/static/wheel_button.png",
}, // 按钮图
},
mounted() {
const widthNum = this._getNum(this.width);
const widthUnit = this._getUnit(this.width);
const prizeWidth = this.prizeWidth;
const paddingTop = this.prizePaddingTop;
this.degValue = this.initDeg;
this.itemTransformOrigin = `50% {0.5 * widthNum}{widthUnit};`;
this.prizeWidth = isNaN(prizeWidth)
? this._calculatePrizeWidth()
: prizeWidth;
this.prizePaddingTop = isNaN(paddingTop)
? this._calculatePrizePaddingTop()
: paddingTop;
// this.count = this.prizeList.length; // 奖品个数
this.rotNum = 0; // 当前是第几次抽奖
this.onRunning = false; // 是否正在抽奖
},
methods: {
init() {},
getIndexByName(name) {
// console.log(this.count,"没走吗====", name);
const list = this.prizeList;
for (let i = 0; i < this.prizeList.length; i++) {
// console.log(list[i].name, "name", name);
if (list[i] && list[i].name == name) return i;
}
return -1;
// const list = this.prizeList;
// for (let i = 0; i < this.count; i++) {
// console.log(list[name].name,"抽奖结果");
// if (i == name) return i;
// }
// return -1;
},
start(e) {
console.log("开始", this.prizeName, "次数", this.rotTimes);
if (this.onRunning) return;
// if (this.rotNum >= this.rotTimes) {
// this.emit('onTimesUp')
// return;
// };
if (this.rotTimes == 0) {
this.emit("onTimesUp");
return;
}
// if (!this.prizeName) {
// throw new Error('请传入抽奖结果名称:prizeName');
// }
const index = this.getIndexByName(this.prizeName);
if (index === -1) {
throw new Error(
`抽奖结果名称与抽奖列表配置项不匹配,未找到名称为{this.prizeName}的奖项`
);
}
this.rotNum += 1;
this.onRunning = true;
// const degree = index * (360 / (this.count * 2));
// const degValue = 360 * this.count * this.rotNum - degree;
// this.degValue = degValue
// 计算目标角度
const singleAngle = 360 / this.prizeList.length;
const targetAngle = singleAngle * index;
const rounds = 5 * this.rotNum; // 每次增加的圈数
const totalAngle = rounds * 360 + (360 - targetAngle);
this.degValue = totalAngle;
this.emit("onStart", this.prizeName, this.rotNum);
setTimeout(() => {
this.done();
}, 6000);
},
done() {
this.onRunning = false;
this.emit("onFinish", this.prizeName, this.rotNum);
// this.onFinish(this.prizeName, this.rotNum);
},
_getNum(s) {
// 获取像素选项数值
return parseFloat(s);
},
_getUnit(s) {
// 获取像素选项单位
s += "";
return (s.match(/[a-z]+/) || [])[0] || "px";
},
_calculatePrizeWidth() {
// 等边三角形内接正方形边长: (4 - 2 * 根号3) * 边长
const widthNum = this._getNum(this.width);
const widthUnit = this._getUnit(this.width);
return (4 - 2 * Math.sqrt(3)) * 0.5 * widthNum + widthUnit;
},
_calculatePrizePaddingTop() {
// 等边三角形一边的中点离过该边两点的圆弧的距离: 边长 - 边长 * (根号3 / 2)
const widthNum = this._getNum(this.width);
const widthUnit = this._getUnit(this.width);
return 0.5 * widthNum - 0.25 * widthNum * Math.sqrt(3) + 20 + widthUnit;
},
},
};
</script>
<style lang="scss" scoped>
.wheel-container {
position: relative;
margin: auto;
border-radius: 50%;
overflow: hidden;
}
.wheel-list {
position: absolute;
border-radius: 50%;
width: inherit;
height: inherit;
transition: all 6s ease;
-webkit-transition: all 6s ease;
background-size: 100% 100%;
background-repeat: no-repeat;
}
.wheel-item {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.wheel-img {
position: relative;
display: block;
margin: 0 auto;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.wheel-img image {
display: block;
width: 20px;
height: 20px;
}
.wheel_num {
font-family: PingFang SC, PingFang SC;
font-weight: 600;
font-size: 28px;
color: #ff824a;
}
.wheel_name {
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #ff824a;
white-space: pre-line;
}
.wheel-btn {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.wheel-btn .img {
width: 68px;
height: 86.28px;
}
</style>
// 使用组件
<Wheel @onStart="onStart" @onFinish="onFinish" :prizeList="prizeList" :prizeName="prizeName" :rotTimes="totalTimes"></Wheel>
//参数
prizeList: [],
prizeName: '10金币',
totalTimes: 0,
curTimes: 0,
result: '',
// 方法
/*
@param name 获奖项名字
@param times 当前转动次数
*/
onStart(name, times) {
console.log(name, times, "开始抽奖");
// 转盘开始转动
// this.setData({
// result: `第{times}次抽奖中,请稍候...`,
// curTimes: times++
// })
if (this.totalTimes>0) {
this.totalTimes -= 1;
}
//this.getOnStart(); // 自己的方法
},
/*
@param name 获奖项名字
@param times 当前转动次数
*/
onFinish(name, times) {
console.log(name, times, "结束抽奖");
//this.getOnFinish(); // 自己的方法
// this.prizeName = Math.floor(Math.random() * 12)
// console.log(this.prizeName, "下次的结果");
// 转盘结束转动
// this.setData({
// result: name === '未中奖' ? '很遗憾,差点就中奖了' : `恭喜你,获得{name}`,
// prizeName: this.data.prizeList[Math.floor(Math.random() * 6)].name,
// })
},
Comments | NOTHING