parent
9fa08b8898
commit
5debfabc01
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed, watch } from 'vue'
|
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -21,6 +21,20 @@ const emit = defineEmits(['collect-seal', 'play-drum', 'height-changed'])
|
||||||
// 是否收集福印
|
// 是否收集福印
|
||||||
const sealCollected = ref(false)
|
const sealCollected = ref(false)
|
||||||
|
|
||||||
|
// 音乐播放状态
|
||||||
|
const isMusicPlaying = ref(false)
|
||||||
|
const musicPlayer = ref(null)
|
||||||
|
|
||||||
|
// 福字点击区域状态
|
||||||
|
const fuClickAreaVisible = ref(true)
|
||||||
|
const sq1ImageVisible = ref(false)
|
||||||
|
|
||||||
|
// 福字点击区域随机位置(限制在y>350的630*400区域内,福字大小100*100)
|
||||||
|
const fuClickPosition = ref({
|
||||||
|
x: Math.random() * 530, // x范围: 0-530rpx(总宽度630rpx - 福字宽度100rpx)
|
||||||
|
y: Math.random() * 300 + 350 // y范围: 350-650rpx(从y>350开始,总高度400rpx - 福字高度100rpx)
|
||||||
|
})
|
||||||
|
|
||||||
// 场景高度
|
// 场景高度
|
||||||
const sceneHeight = ref(0)
|
const sceneHeight = ref(0)
|
||||||
|
|
||||||
|
|
@ -76,15 +90,53 @@ const collectSeal = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放大鼓音效
|
// 点击福字区域
|
||||||
const playDrum = () => {
|
const handleFuClick = () => {
|
||||||
emit('play-drum')
|
if (fuClickAreaVisible.value) {
|
||||||
collectSeal()
|
fuClickAreaVisible.value = false
|
||||||
showToast({
|
sq1ImageVisible.value = true
|
||||||
message: '京韵大鼓,非遗福印!',
|
showToast({
|
||||||
icon: 'info',
|
message: '恭喜获得新春祝福!',
|
||||||
duration: 1500
|
icon: 'success',
|
||||||
})
|
duration: 2000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 控制音乐播放/暂停
|
||||||
|
const toggleMusic = () => {
|
||||||
|
if (!musicPlayer.value) {
|
||||||
|
// 创建音频对象
|
||||||
|
musicPlayer.value = uni.createInnerAudioContext()
|
||||||
|
musicPlayer.value.src = '/static/music/bgm1.mp3'
|
||||||
|
musicPlayer.value.loop = false
|
||||||
|
|
||||||
|
// 监听播放结束
|
||||||
|
musicPlayer.value.onEnded(() => {
|
||||||
|
isMusicPlaying.value = false
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听错误
|
||||||
|
musicPlayer.value.onError((err) => {
|
||||||
|
console.error('音乐播放失败:', err)
|
||||||
|
isMusicPlaying.value = false
|
||||||
|
showToast({
|
||||||
|
message: '音乐播放失败',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMusicPlaying.value) {
|
||||||
|
// 正在播放,点击后停止
|
||||||
|
musicPlayer.value.stop()
|
||||||
|
isMusicPlaying.value = false
|
||||||
|
} else {
|
||||||
|
// 未播放,点击后开始播放
|
||||||
|
musicPlayer.value.play()
|
||||||
|
isMusicPlaying.value = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面挂载时的初始化
|
// 页面挂载时的初始化
|
||||||
|
|
@ -116,6 +168,15 @@ const calculateHeight = () => {
|
||||||
emit('height-changed', sceneHeight.value)
|
emit('height-changed', sceneHeight.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 组件卸载时清理
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (musicPlayer.value) {
|
||||||
|
musicPlayer.value.stop()
|
||||||
|
musicPlayer.value.destroy()
|
||||||
|
musicPlayer.value = null
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -133,54 +194,43 @@ const calculateHeight = () => {
|
||||||
<div class="lantern left-lantern">🏮</div>
|
<div class="lantern left-lantern">🏮</div>
|
||||||
<div class="lantern right-lantern">🏮</div>
|
<div class="lantern right-lantern">🏮</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 福字增强动效 -->
|
<!-- 音乐控制按钮 -->
|
||||||
<div class="fu-word">福</div>
|
<div class="music-control" @click="toggleMusic">
|
||||||
|
<img
|
||||||
|
src="/static/images/icon_music.png"
|
||||||
|
alt="音乐控制"
|
||||||
|
class="music-icon"
|
||||||
|
:class="{ 'playing': isMusicPlaying }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 点击提示 -->
|
<!-- 福字点击区域 -->
|
||||||
<div class="click-indicator" :class="{ 'animate-pulse': !sealCollected }">
|
<div
|
||||||
|
v-if="fuClickAreaVisible"
|
||||||
|
class="fu-click-area"
|
||||||
|
:style="{
|
||||||
|
left: `${fuClickPosition.x}rpx`,
|
||||||
|
top: `${fuClickPosition.y}rpx`
|
||||||
|
}"
|
||||||
|
@click="handleFuClick"
|
||||||
|
>
|
||||||
|
<img src="/static/images/icon_fu.png" alt="福字" class="fu-icon" />
|
||||||
|
<img src="/static/images/icon_hand.png" alt="点击手势" class="hand-icon" />
|
||||||
|
<div class="click-indicator">
|
||||||
<div class="pulse-circle"></div>
|
<div class="pulse-circle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 大鼓交互区域 -->
|
<!-- sq1图片 -->
|
||||||
<div class="drum-interactive-area" @click="playDrum">
|
<img
|
||||||
<!-- 覆盖在图片大鼓上的点击区域 -->
|
v-if="sq1ImageVisible"
|
||||||
</div>
|
src="/static/images/sq1.png"
|
||||||
|
alt="新春祝福"
|
||||||
|
class="sq1-image"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 烟花效果 -->
|
|
||||||
<div class="fireworks">
|
|
||||||
<div class="firework firework-1">🎆</div>
|
|
||||||
<div class="firework firework-2">🎇</div>
|
|
||||||
<div class="firework firework-3">🎆</div>
|
|
||||||
<div class="firework firework-4">🎇</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 人物元素 -->
|
|
||||||
<div
|
|
||||||
class="character"
|
|
||||||
:style="{
|
|
||||||
left: `${characterPosition.x}%`,
|
|
||||||
top: `${characterPosition.y}%`,
|
|
||||||
transform: `translate(-50%, -50%)`
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
🧧
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 烟花效果 -->
|
|
||||||
<div class="fireworks" v-if="showFireworks">
|
|
||||||
<div class="firework firework-1">🎆</div>
|
|
||||||
<div class="firework firework-2">🎇</div>
|
|
||||||
<div class="firework firework-3">🎆</div>
|
|
||||||
<div class="firework firework-4">🎇</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 福印收集标记 -->
|
|
||||||
<div v-if="sealCollected" class="seal-collected-mark">
|
|
||||||
<div class="seal-icon">🏮</div>
|
|
||||||
<div class="seal-text">已收集非遗福印</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -397,6 +447,123 @@ const calculateHeight = () => {
|
||||||
50% { opacity: 1; transform: scale(1.5); }
|
50% { opacity: 1; transform: scale(1.5); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 音乐控制按钮 */
|
||||||
|
.music-control {
|
||||||
|
position: absolute;
|
||||||
|
top: 810rpx;
|
||||||
|
left: 500rpx;
|
||||||
|
width: 82rpx;
|
||||||
|
height: 82rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 30;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-control:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-icon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
opacity: 1;
|
||||||
|
animation: scale 1.5s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scale {
|
||||||
|
0%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 福字点击区域 */
|
||||||
|
.fu-click-area {
|
||||||
|
position: absolute;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 25;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fu-icon {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 74rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
animation: sway 3s infinite ease-in-out;
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sway {
|
||||||
|
0%, 100% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: rotate(-3deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: rotate(3deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hand-icon {
|
||||||
|
position: absolute;
|
||||||
|
width: 38rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
top: 70%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
animation: clickUp 2s infinite ease-in-out;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes clickUp {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0) scale(1.2);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10rpx) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fu-click-area .click-indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 40rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fu-click-area .pulse-circle {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: rgba(255, 215, 0, 0.3);
|
||||||
|
border: 2rpx solid rgba(255, 215, 0, 0.6);
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
animation-delay: 1s; /* hand-icon播放到50%(1秒)后再开始 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sq1图片 */
|
||||||
|
.sq1-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 220rpx;
|
||||||
|
right: -5rpx;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
max-width: 300rpx;
|
||||||
|
z-index: 20;
|
||||||
|
animation: fadeIn 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
/* 福印收集标记 */
|
/* 福印收集标记 */
|
||||||
.seal-collected-mark {
|
.seal-collected-mark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue