You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

289 lines
7.6 KiB

<template>
<view class="audio-control" :style="{top:top}" @click.stop="toggleAudio">
<image v-if="isAudioPlaying" :src="showImg('/uploads/20250904/c7ddc330d25a0916885a31f1d28f6665.png')" mode="" style="width: 80rpx;height: 80rpx;"></image>
<image v-else :src="showImg('/uploads/20250904/057669bd710740650db1cafd414c08c9.png')" mode="" style="width: 80rpx;height: 80rpx;"></image>
</view>
</template>
<script>
export default {
name: 'AudioControl',
inheritAttrs: false,
props: {
// 音频文件路径
audioSrc: {
type: String,
required: true
},
top:{
type:String,
default:'180rpx'
},
// 是否显示组件
visible: {
type: Boolean,
default: true
}
},
data() {
return {
isAudioPlaying: false,
audioContext: null,
backgroundMusicWasPlaying: false, // 记录背景音乐之前的状态
audioInstanceId: null // 音频实例标识
}
},
mounted() {
this.initAudio();
// 监听背景音乐切换事件
uni.$on('backgroundMusicToggle', this.handleBackgroundMusicToggle);
// 页面加载时检查是否有全局音频在播放
this.checkGlobalAudioState();
},
beforeUnmount() {
this.destroyAudio();
// 移除事件监听
uni.$off('backgroundMusicToggle', this.handleBackgroundMusicToggle);
},
methods: {
initAudio() {
try {
// 检查是否已有全局音频实例
const app = getApp();
if (app && app.globalData && app.globalData.currentAudio) {
// 如果有全局音频且URL匹配,则复用
if (app.globalData.currentAudio.src === this.audioSrc) {
this.audioContext = app.globalData.currentAudio;
this.isAudioPlaying = !this.audioContext.paused;
this.setupAudioEvents();
return;
} else {
// 如果URL不匹配,停止之前的音频
app.globalData.currentAudio.stop();
app.globalData.currentAudio.destroy();
}
}
// 创建新的音频上下文
this.audioContext = uni.createInnerAudioContext();
this.audioContext.src = this.audioSrc;
// 保存到全局
if (app && app.globalData) {
app.globalData.currentAudio = this.audioContext;
}
this.setupAudioEvents();
} catch (error) {
console.error('初始化音频失败:', error);
}
},
setupAudioEvents() {
if (!this.audioContext) return;
// 监听音频事件
this.audioContext.onPlay(() => {
this.isAudioPlaying = true;
console.log('音频开始播放');
});
this.audioContext.onPause(() => {
this.isAudioPlaying = false;
console.log('音频暂停');
});
this.audioContext.onStop(() => {
this.isAudioPlaying = false;
console.log('音频停止');
});
this.audioContext.onEnded(() => {
this.isAudioPlaying = false;
// 音频播放结束后恢复背景音乐
this.restoreBackgroundMusic();
console.log('音频播放结束');
});
this.audioContext.onError((err) => {
console.error('音频播放错误:', err);
this.isAudioPlaying = false;
// 发生错误时也恢复背景音乐
this.restoreBackgroundMusic();
});
},
checkGlobalAudioState() {
try {
const app = getApp();
if (app && app.globalData && app.globalData.currentAudio) {
const globalAudio = app.globalData.currentAudio;
// 如果全局音频的URL与当前组件的URL匹配
if (globalAudio.src === this.audioSrc) {
this.isAudioPlaying = !globalAudio.paused;
console.log('同步全局音频状态:', this.isAudioPlaying);
}
}
} catch (error) {
console.error('检查全局音频状态失败:', error);
}
},
toggleAudio() {
if (!this.audioContext) {
console.error('音频上下文未初始化');
return;
}
if (this.isAudioPlaying) {
// 暂停音频,恢复背景音乐
this.pauseAudio();
} else {
// 播放音频,暂停背景音乐
this.playAudio();
}
},
playAudio() {
try {
// 记录背景音乐当前状态并暂停
this.pauseBackgroundMusic();
// 播放音频
this.audioContext.play();
// 发送音频播放事件
uni.$emit('audioPlaying', true);
} catch (error) {
console.error('播放音频失败:', error);
}
},
pauseAudio() {
try {
// 暂停音频
this.audioContext.pause();
// 恢复背景音乐
this.restoreBackgroundMusic();
// 发送音频停止事件
uni.$emit('audioPlaying', false);
} catch (error) {
console.error('暂停音频失败:', error);
}
},
pauseBackgroundMusic() {
try {
const app = getApp();
if (app && app.globalData && app.globalData.bgMusic) {
// 记录背景音乐当前状态
this.backgroundMusicWasPlaying = app.globalData.isMusicPlaying;
// 如果背景音乐正在播放,则暂停
if (this.backgroundMusicWasPlaying) {
app.globalData.bgMusic.pause();
console.log('背景音乐已暂停');
}
}
} catch (error) {
console.error('暂停背景音乐失败:', error);
}
},
restoreBackgroundMusic() {
try {
const app = getApp();
if (app && app.globalData && app.globalData.bgMusic && this.backgroundMusicWasPlaying) {
// 恢复背景音乐播放
app.globalData.bgMusic.play();
console.log('背景音乐已恢复');
}
} catch (error) {
console.error('恢复背景音乐失败:', error);
}
},
destroyAudio() {
// 注意:不销毁全局音频实例,只是断开当前组件的连接
console.log('AudioControl组件销毁,但保持全局音频实例');
// 清空当前组件的引用,但不销毁全局音频
this.audioContext = null;
},
// 处理背景音乐切换事件
handleBackgroundMusicToggle() {
// 如果音频正在播放,则暂停音频(但不恢复背景音乐)
if (this.isAudioPlaying) {
try {
// 只暂停音频,不恢复背景音乐
this.audioContext.pause();
// 发送音频停止事件
uni.$emit('audioPlaying', false);
console.log('背景音乐切换时暂停音频(不恢复背景音乐)');
} catch (error) {
console.error('暂停音频失败:', error);
}
}
}
},
watch: {
// 监听音频源变化
audioSrc: {
handler(newSrc) {
if (this.audioContext && newSrc) {
this.audioContext.src = newSrc;
}
},
immediate: true
}
}
}
</script>
<style lang="scss" scoped>
.audio-control {
position: absolute;
top: 180rpx;
right: 30rpx;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
// background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 998;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
}
.audio-icon {
font-size: 36rpx;
color: #fff;
transition: all 0.3s ease;
}
.playing {
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
</style>