feat: 大转盘抽奖

This commit is contained in:
Burt 2024-01-10 20:28:17 +08:00
parent 5787d29fbc
commit eca4c9f7c0
6 changed files with 189 additions and 0 deletions

BIN
screenshots/lottery2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -59,6 +59,13 @@
"navigationBarTitleText": "九宫格抽奖"
}
},
{
"path": "pages/demo/lottery2",
"type": "page",
"style": {
"navigationBarTitleText": "大转盘抽奖"
}
},
{
"path": "pages/login/login",
"type": "page",

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

181
src/pages/demo/lottery2.vue Normal file
View File

@ -0,0 +1,181 @@
<route lang="json5">
{
style: { navigationBarTitleText: '大转盘抽奖' },
}
</route>
<template>
<view class="mt-4 h-10 text-center">大转盘抽奖</view>
<div class="lottery-box">
<div class="lottery-list">
<div class="lottery-item" v-for="(n, index) in 1" :key="n">
<div class="lottery-item-inner">
<div class="lottery-item-gift">奖品{{ index + 1 }}</div>
</div>
</div>
<div ref="pointer" class="pointer" @click="handleClick">
<div>开始</div>
<div>抽奖</div>
</div>
</div>
</div>
<view class="leading-8">
<view class="mt-8 text-center text-green-600">下面是调试过程图片</view>
<view class="mb-8 text-center text-green-600">欢迎感兴趣的玩家继续优化</view>
<view class="text-center text-blue-600">计算lottery-item-inner节点的padding-left值</view>
<image src="./lottery2-1.png" mode="widthFix" class="w-full" />
<view class="text-center text-blue-600">调整lottery-item-gift节点</view>
<image src="./lottery2-2.png" mode="widthFix" class="w-full" />
</view>
</template>
<script lang="ts" setup>
const giftLen = 8
const deg = 360 / giftLen //
const loop = 4 // 4
const state = reactive({
lottery: 0, //
lastLottery: 0, //
stopDeg: 0, //
loading: false,
})
const pointer = ref()
function handleClick() {
if (state.loading) return
state.loading = true
// 使0~9
state.lottery = Math.floor(Math.random() * giftLen)
console.log(state.lottery)
// +0+
state.stopDeg += (state.lottery + (giftLen - state.lastLottery)) * deg + loop * 360
//
pointer.value.style.transform = `rotate(${state.stopDeg}deg)`
// uniaddEventListener
setTimeout(() => {
state.lastLottery = state.lottery
state.loading = false
// alert(`${state.lottery + 1}`)
uni.showModal({
title: `恭喜获得奖品${state.lottery + 1}`,
})
}, 3000)
}
//
// pointer.value.addEventListener('transitionend', () => {
// alert(`${state.lottery + 1}`)
// //
// state.lastLottery = state.lottery
// state.loading = false
// })
</script>
<style lang="scss">
.lottery-box {
display: flex;
align-items: center;
justify-content: center;
}
.lottery-list {
--size: 600rpx;
--half: calc(var(--size) / 2);
--len: 8; //
--deg: calc(360 / var(--len) * 1deg);
--deg-num: calc(360 / var(--len));
position: relative;
width: var(--size);
height: var(--size);
border: 2px solid #f55;
border-radius: 50%;
}
.lottery-item {
position: absolute;
top: 0;
left: var(--half);
width: var(--half);
height: var(--size);
// overflow: hidden; //
background-color: #ff5350a1; //
transform-origin: left center;
}
.lottery-item-inner {
position: absolute;
top: 0;
left: calc(-1 * var(--half));
box-sizing: border-box;
width: var(--half);
height: var(--size);
padding-left: calc(((1 - sin(var(--deg-num))) * var(--size)));
font-size: 12px;
border-radius: var(--half) 0 0 var(--half);
transform: rotate(var(--deg));
transform-origin: right center;
}
.lottery-item-inner .lottery-item-gift {
display: block;
text-align: center;
transform: rotate(calc(-0.5 * var(--deg))) translateY(16px)
translateX(calc(0.5 * var(--half) * (1 - 1 / cos(0.5 * var(--deg)))));
transform-origin: center;
}
.lottery-item:nth-child(2n + 1) .lottery-item-inner {
background: #fef6e0a1;
}
.lottery-item:nth-child(2n) .lottery-item-inner {
background: #ffffffa1;
}
// TODO --len
@for $i from 1 through 8 {
.lottery-item:nth-child(#{$i}) {
transform: rotate(calc(($i - 1 - 0.5) * var(--deg)));
}
}
.pointer {
--pointer-size: 40px;
--pointer-padding: calc(var(--pointer-size) / 5);
position: absolute;
top: calc(var(--half) - var(--pointer-size) / 2 - var(--pointer-padding));
left: calc(var(--half) - var(--pointer-size) / 2 - var(--pointer-padding));
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: var(--pointer-size);
height: var(--pointer-size);
padding: var(--pointer-padding);
font-size: 12px;
text-align: center;
background-color: #ffffffd1;
border: 1px solid #ff5350;
border-radius: 50%;
transition: transform 3s cubic-bezier(0.2, 0.93, 0.43, 1);
}
.pointer::after {
--caret-size: 8px;
position: absolute;
bottom: calc(var(--pointer-size) + var(--pointer-padding) * 2);
left: calc(var(--pointer-size) / 2 - var(-caret-size) / 2);
content: '';
border-color: transparent;
border-style: solid;
border-width: calc(var(--caret-size) * 2) var(--caret-size);
border-bottom-color: #ff5350;
transform-origin: center;
}
</style>

1
uni-pages.d.ts vendored
View File

@ -7,6 +7,7 @@ interface NavigateToOptions {
url: "pages/index/index" |
"pages/demo/clock" |
"pages/demo/lottery" |
"pages/demo/lottery2" |
"pages/login/login" |
"pages/my/index" |
"pages/throughout/index" |