This commit is contained in:
lcw
2025-11-27 14:27:59 +08:00
parent 93c49dff27
commit 85f1f3a6f7
75 changed files with 1321 additions and 360 deletions

180
src/utils/audioPlayer.js Normal file
View File

@ -0,0 +1,180 @@
// 音频播放器工具类
/**
* 音频播放器类
*/
class AudioPlayerClass {
constructor() {
this.audioPlayer = null;
this.isLoaded = false;
this.isPlaying = false;
}
/**
* 初始化音频播放器
* @param {string} audioPath - 音频文件路径
* @param {boolean} loop - 是否循环播放
* @returns {Promise} - 初始化结果
*/
init(audioPath, loop = true) {
return new Promise((resolve, reject) => {
try {
// 创建Audio对象并加载音频文件
this.audioPlayer = new Audio(audioPath);
this.audioPlayer.loop = loop; // 设置循环播放
// 监听音频加载完成事件
this.audioPlayer.addEventListener('canplaythrough', () => {
console.log('音频加载完成,可以播放');
this.isLoaded = true;
resolve(true);
});
// 监听错误事件
this.audioPlayer.addEventListener('error', (error) => {
console.error('音频加载错误:', error);
console.error('错误代码:', error.code);
console.error('音频网络状态:', this.audioPlayer.networkState);
console.error('音频就绪状态:', this.audioPlayer.readyState);
reject(error);
});
// 预加载音频
console.log('开始预加载音频...');
this.audioPlayer.load();
console.log('音频预加载请求已发送');
} catch (error) {
console.error('初始化音频播放器失败:', error);
console.error('错误详情:', error.stack);
reject(error);
}
});
}
/**
* 播放音频
* @param {boolean} autoUnmute - 是否自动取消静音
* @returns {Promise} - 播放结果
*/
play(autoUnmute = true) {
return new Promise((resolve, reject) => {
if (!this.audioPlayer) {
reject(new Error('音频播放器未初始化'));
return;
}
if (!this.isLoaded) {
reject(new Error('音频未加载完成'));
return;
}
try {
// 严格模式下的播放策略:先设置静音,再取消静音,最后播放
if (autoUnmute) {
this.audioPlayer.muted = true;
// 使用setTimeout确保时序正确
setTimeout(() => {
this.audioPlayer.muted = false;
this.audioPlayer.play()
.then(() => {
this.isPlaying = true;
console.log('音频播放成功');
resolve(true);
})
.catch(error => {
if (error.name === 'NotAllowedError') {
console.error('播放被浏览器自动播放策略阻止,需要用户交互后才能播放');
}
reject(error);
});
}, 0);
} else {
this.audioPlayer.play()
.then(() => {
this.isPlaying = true;
console.log('音频播放成功');
resolve(true);
})
.catch(error => {
if (error.name === 'NotAllowedError') {
console.error('播放被浏览器自动播放策略阻止,需要用户交互后才能播放');
}
reject(error);
});
}
} catch (error) {
console.error('音频播放失败:', error);
reject(error);
}
});
}
/**
* 暂停音频
*/
pause() {
if (this.audioPlayer) {
this.audioPlayer.pause();
this.isPlaying = false;
console.log('音频已暂停');
}
}
/**
* 设置音量
* @param {number} volume - 音量值0-1
*/
setVolume(volume) {
if (this.audioPlayer) {
this.audioPlayer.volume = Math.max(0, Math.min(1, volume));
}
}
/**
* 设置是否静音
* @param {boolean} muted - 是否静音
*/
setMuted(muted) {
if (this.audioPlayer) {
this.audioPlayer.muted = muted;
}
}
/**
* 获取音频播放状态
* @returns {boolean} - 是否正在播放
*/
getIsPlaying() {
return this.isPlaying;
}
/**
* 获取音频加载状态
* @returns {boolean} - 是否已加载完成
*/
getIsLoaded() {
return this.isLoaded;
}
/**
* 销毁音频播放器
*/
destroy() {
if (this.audioPlayer) {
this.audioPlayer.pause();
this.audioPlayer.remove();
this.audioPlayer = null;
this.isLoaded = false;
this.isPlaying = false;
console.log('音频播放器已销毁');
}
}
}
// 导出单例实例
const audioPlayerInstance = new AudioPlayerClass();
export default audioPlayerInstance;
// 导出类(可选,用于创建多个实例)
export { AudioPlayerClass };