Files
faceFamilySource/src/components/Lottery.vue
2025-09-23 15:46:46 +08:00

447 lines
10 KiB
Vue

<template>
<ModalTransition class="lottery" :show="show" name="opacity" position="center">
<div class="lottery-wrapper">
<div class="guang" ref="guangRef"></div>
<div class="guangyun" ref="guangyunRef"></div>
<div class="lottery-scene" ref="sceneRef">
<div class="lottery-card" ref="cardRef">
<div class="lottery-prize">
<div class="lottery-title" :class="props.type === 'notice' && 'notice'" ref="titleRef"
v-show="activePrizeData.prize_code !== 'NO'"></div>
<div class="lottery-desc" v-show="props.type === 'notice'">在刚刚结束的打榜活动中成功斩获<br /><strong>[30]</strong></div>
<div class="lottery-image" :class="'USER_' + activePrizeData.prize_code" ref="lotteryImageRef"></div>
<div class="lottery-name" v-show="activePrizeData.prize_code !== 'NO'">{{ activePrizeData.prize_name }}</div>
<div class="lottery-btngroup" v-show="btngroupShow">
<div class="btn-more" @click="handleBtnMore"></div>
<div class="btn-kaixin" @click="handleLotteryAction" v-if="activePrizeData.prize_code !== 'NO'"></div>
</div>
</div>
</div>
</div>
</div>
</ModalTransition>
</template>
<script setup>
import { gsap } from "gsap";
import { ref, watch, onMounted, onUnmounted } from "vue"
import globalToastEvent, { ToastType } from "../globalToastEvent";
import ModalTransition from "./ModalTransition.vue"
import confetti from "canvas-confetti";
import { Request, Sleep } from "../libs/utils"
import { globalStore } from "@/globalstore";
import getUserPicture from "../libs/getUserPicture";
// const lotteryFaceUrl = ref('')
const cardRef = ref(null)
const sceneRef = ref(null)
const guangRef = ref(null)
const guangyunRef = ref(null)
const lotteryImageRef = ref(null)
const titleRef = ref(null)
const activePrizeData = ref({})
const btngroupShow = ref(false)
gsap.registerPlugin()
const props = defineProps({
show: false,
type: "draw"
})
const emit = defineEmits(['close'])
let interval = null
let gsapCtx = null
let PRIZEDATA = null
const closeThis = () => {
initAnimateStyle()
emit("close")
}
const handleBtnMore = () => {
closeThis()
globalToastEvent.emit(ToastType.SHOW_AD)
}
const handleLotteryAction = () => {
//实物
closeThis()
if (activePrizeData.value.coupon_type === 'scene') {
globalToastEvent.emit(ToastType.SHOW_ADDRESS, activePrizeData.value.id)
}
}
onMounted(() => {
gsap.registerPlugin()
initAnimateStyle()
})
const initAnimateStyle = () => {
interval && clearInterval(interval)
interval = null
let keyframes = [];
const frames = 20; // 关键帧数量
const strength = 5; // 抖动强度
// 生成关键帧
for (let i = 0; i < frames; i++) {
keyframes.push({
x: gsap.utils.random(-strength, strength),
y: gsap.utils.random(-strength, strength),
duration: 0.05 // 每帧的持续时间
});
}
gsap.set(lotteryImageRef.value, { scale: 0 })
gsap.set(guangyunRef.value, { scale: 0, opacity: 1 })
gsap.set(titleRef.value, { scaleY: 0 })
gsap.set(sceneRef.value, { scale: .2 })
gsap.set(cardRef.value, { rotateY: 0 })
btngroupShow.value = false
}
watch(() => props.show, async (newVal) => {
if (!newVal) {
return
}
const loading = weui.loading()
let lottteryResult = null
if (props.type === 'draw') {
lottteryResult = await Request("lottery/draw", { pool: 'game', consume_type: 'points' })
}
// const userPicture = await getUserPicture()
// const preimg = async() => {
// new Promise((resolve) => {
// const img = new Image()
// img.onload = () => resolve(img)
// img.src = userPicture
// })
// }
// await preimg()
// lotteryFaceUrl.value = userPicture
//TODO: 延时测试,上限删掉
// await Sleep(20000)
lottteryResult = await Request("lottery/draw", { pool: 'game', consume_type: 'points' })
// TODO: 测试数据
// lottteryResult = {
// res: { status: 200 },
// json: {
// id: 0,
// code: "xxx",
// prize_code: 'xxx',
// coupon_type: "scene",
// name: "泸州老窖的一瓶酒"
// }
// }
loading.hide()
if (lottteryResult.res.status !== 200) {
emit('close')
return
} else {
globalStore.lotteryCut()
activePrizeData.value = lottteryResult.json
// 未中奖的情况
if (lottteryResult.json.code === 204) {
activePrizeData.value = { prize_code: 'NO', coupon_type: 'NO' }
}
// kapianCover.value = PRIZEDATA.prize_code === '66_POINTS' ? 'POINTS' : PRIZEDATA.prize_code
}
gsapCtx = gsap.context(() => {
initAnimateStyle()
const prizeshowTime = gsap.timeline({
onComplete: () => {
btngroupShow.value = true
}
});
prizeshowTime.to([sceneRef.value], {
duration: 2.5,
scale: 1,
opacity: 1,
ease: "power4.inOut"
})
prizeshowTime.to(lotteryImageRef.value, {
duration: 1,
scale: 1,
ease: "power4.inOut"
}, "-=1.5")
prizeshowTime.to(guangyunRef.value, {
duration: 1.5,
scale: 2,
}, "-=1")
prizeshowTime.to(titleRef.value, {
scaleY: 1,
ease: "elastic.out(1,0.3)"
})
var duration = 4 * 1000;
var animationEnd = Date.now() + duration;
var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
function randomInRange (min, max) {
return Math.random() * (max - min) + min;
}
interval = setInterval(function () {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
var particleCount = 50 * (timeLeft / duration);
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
}, 250);
})
})
onUnmounted(() => {
gsapCtx && gsapCtx.revert()
})
</script>
<style scoped>
.lottery-image.USER_LZ_ZQ_DZJ {
background-image: url("../assets/images/USER_LZ_ZQ_DZJ.webp");
}
.lottery-image.USER_HG_42_GPJ_500ML {
background-image: url("../assets/images/USER_HG_42_GPJ_500ML.webp");
}
.lottery-image.USER_QLL_MH {
background-image: url("../assets/images/USER_QLL_MH.webp");
}
.lottery-image.USER_DZSKSJ {
background-image: url("../assets/images/USER_DZSKSJ.webp");
}
.lottery-image.USER_LZ_ZQ_DZJ_LJW {
background-image: url("../assets/images/USER_LZ_ZQ_DZJ_LJW.webp");
}
.lottery-image.USER_NO {
background-size: 60% auto;
background-position: center center;
background-image: url("../assets/images/USER_NO.webp");
}
.lottery-image.USER_LZ_XS_SPZ_30ML {
background-image: url("../assets/images/USER_LZ_XS_SPZ_30ML.webp");
}
.lottery-image.USER_LZ_DZ_JBGJ {
background-image: url("../assets/images/USER_LZ_DZ_JBGJ.webp");
}
.guang,
.guangyun {
position: absolute;
left: 50%;
margin-left: -66.2vw;
top: 50%;
margin-top: -64.5vw;
width: 129.62963vw;
height: 129.62963vw;
background-repeat: no-repeat;
background-size: 100%;
}
.guang {
background-image: url("../assets/images/guang.webp");
animation: rotateGuang 20s linear infinite;
}
.guangyun {
background-image: url("../assets/images/guangyun.webp");
/* animation: rotateGuangyun 3s linear infinite; */
}
.lottery-title {
position: absolute;
top: 24vw;
left: 50%;
transform: translateX(-50%) !important;
width: 65.462963vw;
height: 19.907407vw;
background-image: url("../assets/images/lottery-title.webp");
background-repeat: no-repeat;
background-size: 100%;
}
.lottery-title.notice {
width: 39.259259vw;
height: 7.12963vw;
background-image: url("../assets/images/notice-title.webp");
}
.lottery-desc {
position: absolute;
top: 32vw;
left: 50%;
transform: translateX(-50%) !important;
width: 81vw;
font-size: 5vw;
font-weight: 700;
text-align: center;
color: rgb(255, 255, 255);
text-shadow:
0 0 0.37037vw #ff0000,
0 0 0.740741vw #ff0000,
0 0 1.111111vw #ff0000,
0.092593vw 0.092593vw 0 #ff0000,
-0.092593vw -0.092593vw 0 #ff0000;
}
.lottery-name {
position: absolute;
bottom: 18vw;
text-align: center;
width: 100%;
font-size: 5vw;
font-weight: 700;
color: rgb(255, 255, 255);
text-shadow:
0 0 0.37037vw #ff0000,
0 0 0.740741vw #ff0000,
0 0 1.111111vw #ff0000,
0.092593vw 0.092593vw 0 #ff0000,
-0.092593vw -0.092593vw 0 #ff0000;
}
.lottery-btngroup {
position: absolute;
bottom: -24vw;
width: 100%;
display: flex;
justify-content: space-evenly;
}
.btn-more {
width: 48.703704vw;
height: 18.240741vw;
background-image: url("../assets/images/btn-more.webp");
background-repeat: no-repeat;
background-size: 100%;
}
.btn-kaixin {
width: 48.703704vw;
height: 18.240741vw;
background-image: url("../assets/images/btn-kaixin.webp");
background-repeat: no-repeat;
background-size: 100%;
}
.lottery-image {
position: absolute;
top: 45vw;
width: 100%;
height: 60vw;
background-position: center bottom;
background-repeat: no-repeat;
background-size: auto 100%;
background-origin: 50% 100%;
}
.lottery-image.HEIGAI_42_GPJ_500ML {
background-image: url("../assets/images/HEIGAI_42_GPJ_500ML.webp");
}
@keyframes rotateGuangyun {
0% {
transform: scale(.3);
opacity: 0;
}
50% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.4);
opacity: 0;
}
}
@keyframes rotateGuang {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
.lottery-scene {
position: relative;
width: 88.055556vw;
height: 148.796296vw;
}
.lottery-card {
position: absolute;
width: 100%;
height: 100%;
top: -14vw;
}
.lottery-face {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.lottery-card img {
width: 100%;
display: block;
}
.lottery-prize {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("../assets/images/prize-bg.webp");
background-repeat: no-repeat;
background-size: 100%;
}
.close {
position: absolute;
width: 8.148148vw;
height: 8.055556vw;
right: 5vw;
top: 0;
background-image: url("../assets/images/icon-close.webp");
background-repeat: no-repeat;
background-size: 100%;
}
</style>