7.11 morning

This commit is contained in:
2025-07-11 13:20:09 +08:00
parent 9d5870b37b
commit 075fb02263
19 changed files with 925 additions and 250 deletions
+28 -5
View File
@@ -17,6 +17,7 @@ const sunEndEle = useTemplateRef('sun-ani-end');
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
async function shoot() {
//sunEle.value?.jumpTo('天上飞')
sunEle.value?.jumpTo('蓄力飞')
@@ -126,9 +127,9 @@ function gameLoop(currentTime = 0) {
giftPos.value = [null, null];
giftShow.value = false;
lastTime = currentTime;
if (giftProgress.value >= giftList.length || 1) {
if (giftProgress.value >= giftList.length ) {
// 游戏结束逻辑
console.log('游戏结束!');
console.log('游戏结束!耗时:', timeSpent.value / 1000, '秒');
gameEnd()
return;
}
@@ -546,6 +547,7 @@ const leaderBoard = ref([
])
const fmtTime = (time: number) => {
time = Math.round(time);
// 将时间格式化为 mm:ss
const minutes = Math.floor(time / 60);
const seconds = time % 60;
@@ -609,7 +611,7 @@ async function finishCollect() {
<AniEle :url="assets.ani.下拉蓄力提示" ref="aniEle" :height="334" :width="337" :rules="[
{ name: '蓄力', frame: 241, loop: 2 },
]" class="abs arrow" style="bottom: 7%;width: 30vw;left: 35%;" @pointerdown="shoot" />
]" class="abs arrow" style="bottom: 7%;width: 30vw;left: 35%;" @pointerdown.once="shoot" />
<img class="cloud" src="../assets/game/云.png" v-for="c in [
@@ -712,7 +714,7 @@ async function finishCollect() {
]" style="width: 100%; height: auto;" />
</div>
<img src="../assets/game/完成收集.png" alt="" v-if="showScore" class="finish-collect abs" @click="finishCollect"
<img src="../assets/game/完成收集.png" alt="" v-if="showScore" class="finish-collect abs" @click.once="finishCollect"
style="bottom: 8%;left: 33%;width: 34vw;animation: scale-in 0.3s ease-out;">
@@ -736,6 +738,27 @@ async function finishCollect() {
<img src="../assets/game/再玩一次.png" alt="" class="abs"
style="width: 34vw;bottom: -19%;left: 51%;animation: last-btn-in 0.3s ease-out forwards; animation-delay: 200ms;">
<div class="time-spent abs" style="left: 10%; top:44%;width: 24%; display: flex;
align-items: center; flex-direction: column;">
<div class="line-1"
style="display: flex; align-items: center; gap: 1vw; animation: line-in 0.5s ease-out 0.6s forwards;transform: translateX(-210%);;">
<div class="username" style="font-size: 2.9vw;">{{ userdata.username }}</div>
<div class="cost-info"
style="font-size: 2.9vw; color: white; display: flex;align-items: center;justify-content: center;background-color: black;padding: 0 1.2vw; height: 4.5vw; border-radius: 4vw;">
用时</div>
</div>
<div class="time"
style="font-size: 9vw;animation: line-in 0.5s ease-out 0.8s forwards;transform: translateX(-210%);">
{{ fmtTime(timeSpent/1000) }}</div>
</div>
<div class="region-area abs" style="left: 10%; top:30%;width: 24%;height: 10%;gap:2vw; display: flex;animation: line-in 0.5s ease-out 0.4s forwards;transform: translateX(-210%);
align-items: center; flex-direction: column;justify-content: center;">
<div class="region" style="width: 20vw; background-color: white;font-size: 3vw;text-align: center;height: 4.5vw;line-height: 4.5vw; border-radius: 4.5vw;">{{ userdata.region }}</div>
<div class="store" style="font-size: 2.8vw; color: gray;">{{ userdata.store }}</div>
</div>
</div>
@@ -812,7 +835,7 @@ async function finishCollect() {
@keyframes line-in {
from {
transform: translateX(-150%);
transform: translateX(-210%);
}
to {
+53 -90
View File
@@ -6,7 +6,7 @@ import { regions, type RegionData, type Store } from '../data';
import AniEle from '../components/AniEle.vue';
const regionsPos = [
{ w: 68.8, h: 68.8, l: -1, t: -4, src: assets.p1.大北区, tt: '大北区', trt: -13, ad: 6, key: '大北区' },
{ w: 68.8, h: 68.8, l: -1, t: 0, src: assets.p1.大北区, tt: '大北区', trt: -13, ad: 6, key: '大北区' },
{ w: 73.3, h: 73.3, l: 44, t: 20, src: assets.p1.大东区, tt: '大东区', ad: 3, key: '大东区' },
{ w: 62.3, h: 63.7, l: -32, t: 72, src: assets.p1['大南区&免税'], tt: '大南区&免税', trt: 5, ad: 3, key: '大南区&免税' },
{ w: 59.6, h: 59.6, l: -37, t: 15, src: assets.p1.大西区, tt: '大西区', ad: 5, key: '大西区' },
@@ -112,6 +112,7 @@ function startExploration() {
alert('请输入你的名字!');
return;
}
startExplorationRules.value[0].reverse = true;
emit('startExploration', {
region: selectedRegion.value,
store: selectedStores.value[selectedStoreIndex.value].店铺,
@@ -122,7 +123,6 @@ function startExploration() {
// 动画管理
let fadeInAnimations: Animation[] = [];
let swapInAnimations: Animation[] = [];
let scaleInAnimations: Animation[] = [];
let bubbleDropAnimations: Animation[] = [];
// 保存所有动画的数组
@@ -160,38 +160,6 @@ function createSwapInAnimation(element: Element, delay: number = 0) {
return animation;
}
// Scale in 动画(容器)
function createScaleInContainerAnimation(element: Element, delay: number = 0) {
const animation = element.animate([
{ transform: 'scale(0)' },
{ transform: 'scale(1)' }
], {
duration: 500,
easing: 'cubic-bezier(0.5, 0, 0.71, 1.85)',
delay: (delay + 0.2) * 1000,
fill: 'forwards'
});
scaleInAnimations.push(animation);
allAnimations.push(animation);
return animation;
}
// Scale in 动画(文本)
function createScaleInTextAnimation(element: Element, delay: number = 0) {
const animation = element.animate([
{ transform: 'scale(0)' },
{ transform: 'scale(1)' }
], {
duration: 500,
easing: 'cubic-bezier(0.5, 0, 0.71, 1.5)',
delay: (delay + 0.2 + 0.1) * 1000,
fill: 'forwards'
});
scaleInAnimations.push(animation);
allAnimations.push(animation);
return animation;
}
// 气泡下降动画
function createBubbleDropAnimation(element: Element, startTop: string, startLeft: string, endTop: string, endLeft: string, delay: number = 0, duration: number = 600) {
const animation = element.animate([
@@ -216,15 +184,18 @@ function createBubbleDropAnimation(element: Element, startTop: string, startLeft
return animation;
}
const mainLogo = useTemplateRef('main-logo');
const mainLogoRules = ref([
{ name: 'main', frame: 41, loop: 1, pauseAfter: true, duration: 33, reverse: false }
]);
const selectInfoRules = ref([{ name: 'main', frame: 26, loop: 1, duration: 33, reverse: false }]);
const startExplorationRules = ref([{ name: 'start', frame: 19, loop: 1, duration: 33, reverse: false }]);
// 反向播放所有动画来淡出
function reverseAllAnimations() {
mainLogoRules.value[0].reverse = true;
selectInfoRules.value[0].reverse = true;
allAnimations.forEach(animation => {
// 确保动画已经完成
if (animation.playState === 'finished') {
@@ -252,9 +223,13 @@ function fadeOutAllAnimations() {
(window as any).reverseAllAnimations = reverseAllAnimations;
(window as any).fadeOutAllAnimations = fadeOutAllAnimations;
const showSelectInfo = ref(false);
const showSun = ref(false);
onMounted(() => {
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
// 等待一帧确保所有元素都已渲染
requestAnimationFrame(() => {
requestAnimationFrame(async () => {
// 初始化logo淡入动画
const logo = document.querySelector('.logo');
if (logo) {
@@ -269,21 +244,6 @@ onMounted(() => {
createSwapInAnimation(element, delay);
});
// 初始化scale-in动画
const scaleInContainers = document.querySelectorAll('.scale-in-ctn');
scaleInContainers.forEach((element) => {
const htmlElement = element as HTMLElement;
const delay = parseFloat(htmlElement.style.getPropertyValue('--base-delay')?.replace('s', '') || '0');
createScaleInContainerAnimation(element, delay);
});
const scaleInTexts = document.querySelectorAll('.scale-in-txt');
scaleInTexts.forEach((element) => {
const htmlElement = element as HTMLElement;
const delay = parseFloat(htmlElement.style.getPropertyValue('--base-delay')?.replace('s', '') || '0');
createScaleInTextAnimation(element, delay);
});
// 初始化气泡动画
const regionBubbles = document.querySelectorAll('.region-bubble');
regionBubbles.forEach((bubble, index) => {
@@ -365,6 +325,11 @@ onMounted(() => {
bubble.addEventListener('pointerdown', pDown);
bubble.addEventListener('pointerup', pUp, { once: true });
});
await wait(1300);
showSelectInfo.value = true;
await wait(300);
showSun.value = true;
});
});
@@ -381,7 +346,12 @@ onUnmounted(() => {
<img :src="assets.p1.蓝天" alt="" class="bg">
<AniEle :url="assets.ani.主标出现" :width="1015" :height="336" :rules="mainLogoRules"
style="top: 10%;width: 84%;left: 8%;" ref="main-logo" />
style="top: 10%;width: 84%;left: 8%;" />
<div class="sun-warp" v-if="showSun">
<AniEle :url="assets.ani.P1太阳总" :width="1000" :height="1000"
:rules="[{ name: '下落', frame: 69, loop: 1, duration: 33 }, { name: '循环', frame: 75, loop: 0, duration: 33, reverse: false }]" />
</div>
<!-- <img :src="assets.p1.太阳" alt="" style="top: 30%;left: 5%;width: 26%;"> -->
<div style="width: 86vw;height: 86vw;top: 47%; left: 50%;transform: translate3d(-50%, -50%, 0); z-index: -1;">
@@ -400,31 +370,10 @@ onUnmounted(() => {
</div>
</div>
<div style="color: white; bottom: 16%;left: 50%;transform: translateX(-50%); font-size: 4.5vw;">
<span class="block tag scale-in-ctn"
style="background-color: #000;top: -1vw;left: -12vw;color: transparent;transform: scale(0);--base-delay:1s;">
<span>点击</span>
</span>
<span class="block tag scale-in-ctn"
style="background-color: #304A7B;top: 4vw;left: -6vw;color: transparent;transform: scale(0);--base-delay:1.1s;">
<span>选择</span>
</span>
<span class="block tag scale-in-ctn"
style="background-color: #8FBE56;top: .8vw;left: 4.5vw;color: transparent;transform: scale(0);--base-delay:1.1s;">
<span>阵营</span>
</span>
<span class="block tag scale-in-txt"
style="background-color: transparent;top: -1vw;left: -12vw;transform: scale(0);--base-delay:1.2s;">
<span>点击</span>
</span>
<span class="block tag scale-in-txt"
style="background-color: transparent;top: 4vw;left: -6vw;transform: scale(0);--base-delay:1.2s;">
<span>选择</span>
</span>
<span class="block tag scale-in-txt"
style="background-color: transparent;top: .8vw;left: 4.5vw;transform: scale(0);--base-delay:1.3s;">
<span>阵营</span>
</span>
<div style="inset: 0;width: 100%;top: 52%;pointer-events: none;" v-if="showSelectInfo">
<AniEle :url="assets.ani.点击选择阵营" :width="1179" :height="2462" ref="click-select-ani"
:rules="selectInfoRules" />
</div>
<!-- 店铺选择界面 -->
@@ -454,16 +403,34 @@ onUnmounted(() => {
</div>
</div>
<div class="action-buttons relative">
<div class="start-button relative" @click="startExploration">
</div>
</div>
<AniEle :url="assets.ani.开始探索" :width="548" :height="143" :rules="startExplorationRules" class="start-button relative"
@click="startExploration">
</AniEle>
</div>
</div>
</section>
</template>
<style scoped lang="scss">
@keyframes sun-drop {
0% {
transform: translateY(-90vw);
}
100% {
transform: translateY(0);
}
}
.sun-warp {
top: 32%;
width: 24%;
left: 4.5%;
z-index: -1;
transform: translateY(-90vw);
animation: sun-drop 1s cubic-bezier(0.54, 0.46, 0.44, 1.28) forwards;
}
@mixin center {
display: flex;
justify-content: center;
@@ -535,7 +502,7 @@ img {
.bg {
position: absolute;
z-index: -1;
z-index: -11;
inset: 0;
width: 100%;
object-fit: cover;
@@ -675,13 +642,9 @@ img {
.start-button {
width: 40vw;
height: 15vw;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
left: 30%;
cursor: pointer;
background-image: url('../assets/p1/开始探索.png');
transition: all 0.3s ease;
transition: all 0.1s ease;
}
.start-button:hover {