2025-11-27 14:27:59 +08:00
|
|
|
|
// 音频播放器工具类
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 音频播放器类
|
|
|
|
|
|
*/
|
|
|
|
|
|
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', () => {
|
|
|
|
|
|
this.isLoaded = true;
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听错误事件
|
|
|
|
|
|
this.audioPlayer.addEventListener('error', (error) => {
|
|
|
|
|
|
reject(error);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.audioPlayer.load();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
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;
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
})
|
2026-04-15 16:04:50 +08:00
|
|
|
|
.catch(error => reject(error));
|
2025-11-27 14:27:59 +08:00
|
|
|
|
}, 0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.audioPlayer.play()
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
this.isPlaying = true;
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
if (error.name === 'NotAllowedError') {
|
2026-04-15 16:04:50 +08:00
|
|
|
|
// 浏览器自动播放策略阻止,静默忽略
|
2025-11-27 14:27:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
reject(error);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('音频播放失败:', error);
|
|
|
|
|
|
reject(error);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 暂停音频
|
|
|
|
|
|
*/
|
|
|
|
|
|
pause() {
|
|
|
|
|
|
if (this.audioPlayer) {
|
|
|
|
|
|
this.audioPlayer.pause();
|
|
|
|
|
|
this.isPlaying = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置音量
|
|
|
|
|
|
* @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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 导出单例实例
|
|
|
|
|
|
const audioPlayerInstance = new AudioPlayerClass();
|
|
|
|
|
|
export default audioPlayerInstance;
|
|
|
|
|
|
|
|
|
|
|
|
// 导出类(可选,用于创建多个实例)
|
|
|
|
|
|
export { AudioPlayerClass };
|