From e7cc71d841c144998ce222c7287df27aec6a6842 Mon Sep 17 00:00:00 2001 From: Wenzhe Date: Wed, 4 Feb 2026 21:27:25 +0800 Subject: [PATCH] v1.2.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、结束页按钮间隔位置样式调整 2、首页滑动提示修改 3、bgm播放、鼓声播放、视频播放需要相互停止,保证同一时间内只有一种声音在播放 --- components/ChongwenScene.vue | 4 +- components/DongzhimenScene.vue | 4 +- components/EndPage.vue | 5 +- components/LongfusiScene.vue | 4 +- components/QianmenScene.vue | 96 ++++++++++++------- components/SinglePageContainer.vue | 142 ++++++++++++++++++++++++++++- components/WangfujingScene.vue | 4 +- 7 files changed, 217 insertions(+), 42 deletions(-) diff --git a/components/ChongwenScene.vue b/components/ChongwenScene.vue index 0445ae5..4a175df 100644 --- a/components/ChongwenScene.vue +++ b/components/ChongwenScene.vue @@ -23,7 +23,7 @@ const props = defineProps({ }) // 组件事件 -const emit = defineEmits(['collect-seal']) +const emit = defineEmits(['collect-seal', 'video-open', 'video-close']) // 是否收集福印 const sealCollected = ref(false) @@ -67,11 +67,13 @@ const openWebview = () => { // 打开视频播放器 const openVideoPlayer = () => { showVideoPlayer.value = true + emit('video-open') } // 关闭视频播放器 const closeVideoPlayer = () => { showVideoPlayer.value = false + emit('video-close') } // 页面挂载时的初始化 diff --git a/components/DongzhimenScene.vue b/components/DongzhimenScene.vue index 9d315a2..5dbd0a0 100644 --- a/components/DongzhimenScene.vue +++ b/components/DongzhimenScene.vue @@ -23,7 +23,7 @@ const props = defineProps({ } }) -const emit = defineEmits(['collect-seal']) +const emit = defineEmits(['collect-seal', 'video-open', 'video-close']) // sq3图片显示状态 const sq3ImageVisible = ref(false) @@ -478,11 +478,13 @@ const resetDuckPosition = () => { // 打开视频播放器 const openVideoPlayer = () => { showVideoPlayer.value = true + emit('video-open') } // 关闭视频播放器 const closeVideoPlayer = () => { showVideoPlayer.value = false + emit('video-close') } // 预加载图片 diff --git a/components/EndPage.vue b/components/EndPage.vue index 3a4620f..41063c2 100644 --- a/components/EndPage.vue +++ b/components/EndPage.vue @@ -293,11 +293,14 @@ onMounted(() => { .end-buttons { display: flex; - gap: 20px; justify-content: center; margin-bottom: 60px; } +.end-buttons .function-image:not(:last-child) { + margin-right: 20px; +} + .function-btn { cursor: pointer; width: 306rpx; diff --git a/components/LongfusiScene.vue b/components/LongfusiScene.vue index 8308e07..d2e9886 100644 --- a/components/LongfusiScene.vue +++ b/components/LongfusiScene.vue @@ -25,7 +25,7 @@ const props = defineProps({ }) // 组件事件 -const emit = defineEmits(['collect-seal']) +const emit = defineEmits(['collect-seal', 'video-open', 'video-close']) // sq3图片显示状态 const sq3ImageVisible = ref(false) @@ -108,11 +108,13 @@ const closeGallery = () => { // 打开视频播放器 const openVideoPlayer = () => { showVideoPlayer.value = true + emit('video-open') } // 关闭视频播放器 const closeVideoPlayer = () => { showVideoPlayer.value = false + emit('video-close') } // 页面挂载时的初始化 diff --git a/components/QianmenScene.vue b/components/QianmenScene.vue index 601d2c5..42faa92 100644 --- a/components/QianmenScene.vue +++ b/components/QianmenScene.vue @@ -19,19 +19,28 @@ const props = defineProps({ videoUrl: { type: String, default: '' + }, + // 全局BGM播放状态 + isMusicPlaying: { + type: Boolean, + default: false } }) // 组件事件 -const emit = defineEmits(['collect-seal', 'height-changed']) +const emit = defineEmits(['collect-seal', 'height-changed', 'video-open', 'video-close', 'pause-bgm', 'resume-bgm']) // 是否收集福印 const sealCollected = ref(false) -// 音乐播放状态 -const isMusicPlaying = ref(false) +// 音乐播放状态(由父组件控制) const musicPlayer = ref(null) +// 鼓声音频状态 +const isDrumPlaying = ref(false) +const drumPlayer = ref(null) +const wasBgPlayingBeforeDrum = ref(false) + // 福字点击区域状态 const sq1ImageVisible = ref(false) // 视频播放状态 @@ -79,7 +88,7 @@ const parallaxOffset = computed(() => { return offset }) -// 控制音乐播放/暂停 +// 控制鼓声播放/暂停 const toggleMusic = () => { // 第一次点击音乐按钮时收集福印 if (!sealCollected.value) { @@ -88,38 +97,48 @@ const toggleMusic = () => { emit('collect-seal') } - if (!musicPlayer.value) { - // 创建音频对象 - musicPlayer.value = uni.createInnerAudioContext() - const bgmUrl = new URL('/static/music/bgm1.mp3', import.meta.url) - musicPlayer.value.src = bgmUrl.href - musicPlayer.value.loop = false + if (!drumPlayer.value) { + // 创建鼓声音频对象 + drumPlayer.value = uni.createInnerAudioContext() + const drumUrl = new URL('/static/music/bgm1.mp3', import.meta.url) + drumPlayer.value.src = drumUrl.href + drumPlayer.value.loop = false // 监听播放结束 - musicPlayer.value.onEnded(() => { - isMusicPlaying.value = false + drumPlayer.value.onEnded(() => { + isDrumPlaying.value = false + // 恢复BGM播放状态 + emit('resume-bgm') }) // 监听错误 - musicPlayer.value.onError((err) => { - console.error('音乐播放失败:', err) - isMusicPlaying.value = false - showToast({ - message: '音乐播放失败', - icon: 'error', + drumPlayer.value.onError((err) => { + console.error('鼓声播放失败:', err) + isDrumPlaying.value = false + // 恢复BGM播放状态 + emit('resume-bgm') + uni.showToast({ + title: '鼓声播放失败', + icon: 'none', duration: 1500 }) }) } - if (isMusicPlaying.value) { + if (isDrumPlaying.value) { // 正在播放,点击后停止 - musicPlayer.value.stop() - isMusicPlaying.value = false + drumPlayer.value.stop() + isDrumPlaying.value = false + // 恢复BGM播放状态 + emit('resume-bgm') } else { - // 未播放,点击后开始播放 - musicPlayer.value.play() - isMusicPlaying.value = true + // 保存BGM状态 + wasBgPlayingBeforeDrum.value = props.isMusicPlaying + // 暂停BGM + emit('pause-bgm') + // 播放鼓声 + drumPlayer.value.play() + isDrumPlaying.value = true } } @@ -155,12 +174,23 @@ const calculateHeight = () => { // 打开视频播放器 const openVideoPlayer = () => { + // 如果鼓声正在播放,停止鼓声 + if (isDrumPlaying.value && drumPlayer.value) { + drumPlayer.value.stop() + isDrumPlaying.value = false + drumPlayer.value.destroy() + drumPlayer.value = null + // 恢复BGM播放状态 + emit('resume-bgm') + } showVideoPlayer.value = true + emit('video-open') } // 关闭视频播放器 const closeVideoPlayer = () => { showVideoPlayer.value = false + emit('video-close') } // 组件卸载时清理 @@ -170,6 +200,11 @@ onUnmounted(() => { musicPlayer.value.destroy() musicPlayer.value = null } + if (drumPlayer.value) { + drumPlayer.value.stop() + drumPlayer.value.destroy() + drumPlayer.value = null + } }) @@ -180,23 +215,14 @@ onUnmounted(() => { 前门商圈 - - -
- -
-
🏮
-
🏮
-
-
音乐控制
diff --git a/components/SinglePageContainer.vue b/components/SinglePageContainer.vue index 1ff9178..d51b35b 100644 --- a/components/SinglePageContainer.vue +++ b/components/SinglePageContainer.vue @@ -117,6 +117,10 @@ const scenes = ref([ const sceneInteractiveStates = ref(scenes.value.map(() => false)) // 福印收集状态 const sealCollectedStates = ref(scenes.value.map(() => false)) +// 视频播放状态 +const isVideoPlaying = ref(false) +// 鼓声播放状态 +const isDrumPlaying = ref(false) // 计算当前收集的物品 const collectedItems = computed(() => { @@ -140,6 +144,11 @@ const collectionProgress = computed(() => { return Math.round((collected / total) * 100) }) +// 计算是否禁用BGM控制按钮 +const isBgmButtonDisabled = computed(() => { + return isVideoPlaying.value || isDrumPlaying.value +}) + // 计算福印收集对象(传递给 EndPage) const collectedSeals = computed(() => { return { @@ -325,6 +334,9 @@ const initMusicPlayer = () => { // 播放/暂停音乐 const toggleMusic = () => { + // 如果按钮被禁用,不处理点击 + if (isBgmButtonDisabled.value) return + if (!audioPlayer.value) { initMusicPlayer() } @@ -599,6 +611,105 @@ const handleQianmenHeightChanged = (height) => { console.log('当前CSS变量:', getComputedStyle(document.documentElement).getPropertyValue('--scene-height')) } +// 跟踪视频打开前的BGM状态 +const wasMusicPlayingBeforeVideo = ref(false) + +// 跟踪鼓声开始前的BGM状态 +const wasMusicPlayingBeforeDrum = ref(false) + +// 处理视频打开事件 +const handleVideoOpen = () => { + // 标记视频正在播放 + isVideoPlaying.value = true + + // 保存原始BGM状态 + wasMusicPlayingBeforeVideo.value = isMusicPlaying.value + + // 停止全局BGM播放 + if (audioPlayer.value && isMusicPlaying.value) { + audioPlayer.value.pause() + isMusicPlaying.value = false + console.log('全局BGM已停止(视频播放中)') + } +} + +// 处理视频关闭事件 +const handleVideoClose = () => { + // 标记视频已停止播放 + isVideoPlaying.value = false + + // 恢复全局BGM到原始状态 + if (audioPlayer.value && wasMusicPlayingBeforeVideo.value && !isMusicPlaying.value) { + try { + const result = audioPlayer.value.play() + // 检查play()方法是否返回Promise(Web平台) + if (result && typeof result.then === 'function') { + // Web平台:使用Promise处理 + result.then(() => { + isMusicPlaying.value = true + console.log('全局BGM已恢复播放(视频已关闭)') + }).catch(error => { + console.error('BGM恢复播放失败(需要用户交互):', error) + // 不更新isMusicPlaying状态,保持为false + }) + } else { + // 其他平台:同步处理 + isMusicPlaying.value = true + console.log('全局BGM已恢复播放(视频已关闭)') + } + } catch (error) { + console.error('BGM恢复播放失败(需要用户交互):', error) + // 不更新isMusicPlaying状态,保持为false + } + } +} + +// 暂停BGM(用于鼓声播放) +const pauseBgm = () => { + // 标记鼓声正在播放 + isDrumPlaying.value = true + + // 保存原始BGM状态 + wasMusicPlayingBeforeDrum.value = isMusicPlaying.value + + if (audioPlayer.value && isMusicPlaying.value) { + audioPlayer.value.pause() + isMusicPlaying.value = false + console.log('全局BGM已暂停(鼓声播放中)') + } +} + +// 恢复BGM(用于鼓声结束) +const resumeBgm = () => { + // 标记鼓声已停止播放 + isDrumPlaying.value = false + + // 恢复BGM到原始状态 + if (audioPlayer.value && wasMusicPlayingBeforeDrum.value && !isMusicPlaying.value) { + try { + const result = audioPlayer.value.play() + // 检查play()方法是否返回Promise(Web平台) + if (result && typeof result.then === 'function') { + // Web平台:使用Promise处理 + result.then(() => { + isMusicPlaying.value = true + console.log('全局BGM已恢复播放(鼓声已结束)') + }).catch(error => { + console.error('BGM恢复播放失败(需要用户交互):', error) + // 不更新isMusicPlaying状态,保持为false + }) + } else { + // 其他平台:同步处理 + isMusicPlaying.value = true + console.log('全局BGM已恢复播放(鼓声已结束)') + } + } catch (error) { + console.error('BGM恢复播放失败(需要用户交互):', error) + // 不更新isMusicPlaying状态,保持为false + } + } +} + // 使用scroll-view组件后,不再需要手动处理触摸事件 // scroll-view会自动处理触摸滚动 @@ -613,7 +724,7 @@ onUnmounted(() => {
音乐 @@ -661,6 +772,8 @@ onUnmounted(() => { :scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0" :video-url="scenes[1].videoUrl" @collect-seal="collectSeal(1)" + @video-open="handleVideoOpen" + @video-close="handleVideoClose" /> @@ -669,6 +782,8 @@ onUnmounted(() => { :scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0" :video-url="scenes[2].videoUrl" @collect-seal="collectSeal(2)" + @video-open="handleVideoOpen" + @video-close="handleVideoClose" /> @@ -677,6 +792,8 @@ onUnmounted(() => { :scroll-position="scrollContainer?.value?.scrollTop || 0" :video-url="scenes[3].videoUrl" @collect-seal="collectSeal(3)" + @video-open="handleVideoOpen" + @video-close="handleVideoClose" /> @@ -685,6 +802,8 @@ onUnmounted(() => { :scroll-position="scrollContainer?.value?.scrollTop || 0" :video-url="scenes[4].videoUrl" @collect-seal="collectSeal(4)" + @video-open="handleVideoOpen" + @video-close="handleVideoClose" /> @@ -692,8 +811,13 @@ onUnmounted(() => { :active="activeSceneIndex === 5" :scroll-position="scrollContainer?.value?.scrollTop || 0" :video-url="scenes[5].videoUrl" + :is-music-playing="isMusicPlaying" @collect-seal="collectSeal(5)" @height-changed="handleQianmenHeightChanged" + @video-open="handleVideoOpen" + @video-close="handleVideoClose" + @pause-bgm="pauseBgm" + @resume-bgm="resumeBgm" /> @@ -729,7 +853,7 @@ onUnmounted(() => {
滑动提示 -

向上滑动探索商圈

+

向下滑动探索商圈

@@ -965,6 +1089,20 @@ onUnmounted(() => { justify-content: center; z-index: 1000; cursor: pointer; + transition: all 0.3s ease; +} + +.music-control:hover:not(.disabled) { + transform: scale(1.1); +} + +.music-control:active:not(.disabled) { + transform: scale(0.95); +} + +.music-control.disabled { + opacity: 0.5; + cursor: not-allowed; } diff --git a/components/WangfujingScene.vue b/components/WangfujingScene.vue index a6a474e..05c39e7 100644 --- a/components/WangfujingScene.vue +++ b/components/WangfujingScene.vue @@ -25,7 +25,7 @@ const props = defineProps({ }) // 组件事件 -const emit = defineEmits(['collect-seal']) +const emit = defineEmits(['collect-seal', 'video-open', 'video-close']) // 福字点击区域状态 const sq3ImageVisible = ref(false) @@ -106,11 +106,13 @@ const closeGallery = () => { // 打开视频播放器 const openVideoPlayer = () => { showVideoPlayer.value = true + emit('video-open') } // 关闭视频播放器 const closeVideoPlayer = () => { showVideoPlayer.value = false + emit('video-close') } // 页面挂载时的初始化