enum PlayStatus { none, playBefore, play, playFail, pause } enum TriggerAudioListener { fail='fail', canplay='canplay', ended='ended', speed='speed', status='status' } class CustomAudio { audio:HTMLAudioElement = undefined; src:string = ''; triggers:Record={}; status:PlayStatus = PlayStatus.none // 设置播放路径 setSrc(src:string){ if (!CustomAudio.supper) return; if (src && src !== this.src) { // 清空所有监听事件 this.triggers = {}; this.src = src; this.status = PlayStatus.none; if (this.audio === undefined) { this.audio = document.createElement('audio'); this.audio.setAttribute('style','display:none'); this.audio.src = src; // 播放结束 this.audio.addEventListener('ended', ()=> { this.setStatus(PlayStatus.pause); return this.triggerListener(TriggerAudioListener.canplay,{ duration: this.getDuration(this.audio.duration) }); }, false); // 加载就绪 this.audio.addEventListener('canplay', ()=> { return this.triggerListener(TriggerAudioListener.canplay,{ duration: this.getDuration(this.audio.duration) }); }, false); // 加载失败 this.audio.addEventListener('error', ()=> { return this.triggerListener(TriggerAudioListener.fail,{ message:'加载失败' }); }, false); document.body.appendChild(this.audio); } else { this.audio.src = src; } } return this; } getDuration(duration:number){ duration = parseFloat(duration.toFixed(2)); return Math.floor(duration); } // 播放 play(){ if (!this.audio || this.status === PlayStatus.play || this.status === PlayStatus.playBefore) return; this.setStatus(PlayStatus.playBefore); this.audio.play().then(()=>{ this.setStatus(PlayStatus.play); }).catch(()=>{ this.setStatus(PlayStatus.playFail); }); return this; } private triggerTime; triggerSpeed(){ clearTimeout(this.triggerTime); let params = { duration: this.getDuration(this.audio.duration), currDuration: this.getDuration(this.audio.currentTime) }; let diff = this.audio.duration - this.audio.currentTime; this.triggerListener(TriggerAudioListener.speed,params); if (diff > 0) { this.triggerTime = setTimeout(()=> this.triggerSpeed(),1000); } else { return ; } } // 暂停 paused(){ if (!this.audio || this.status === PlayStatus.pause) return; this.setStatus(PlayStatus.pause); this.audio.pause(); return this; } setStatus(status:PlayStatus){ if (this.status !== status) { this.status = status; if (status === PlayStatus.play) { this.triggerSpeed(); } else { clearTimeout(this.triggerTime); } return this.triggerListener(TriggerAudioListener.status,status); } } addListener(key:TriggerAudioListener,callback:Function) { if (!callback) return; if (this.triggers[key] === undefined) this.triggers[key] = [callback]; else this.triggers[key].push(callback); return this; } removeListener(key:TriggerAudioListener,callback:Function) { if (!callback || this.triggers[key] === undefined) return; let index = this.triggers[key].indexOf(callback); if (index>=0) this.triggers[key].splice(index,1); return this; } triggerListener(key:TriggerAudioListener,data?:any) { if (this.triggers[key]) { this.triggers[key].map((item)=> item && item(data)); } } static supper:boolean = !!(document.createElement('audio').canPlayType) } export {CustomAudio,TriggerAudioListener,PlayStatus}; export default new CustomAudio();