使用h5 audio api播放音頻
獲取audio 的3種方式 :
1,使用瀏覽器提供的原生對象
const audio = new Audio()
2,創建音頻標簽的形式
const audio = document.createElement('audio')
3,html頁面直接使用音頻標簽然后通過js代碼獲取
<audio id="audio"></audio> <script> const audio = document.getElementById('audio') </script>
audio元素的屬性及方法在這里不多加講解,詳情請自行參考api文檔(也可以點擊這里喲)
選用第1種方式來操作音頻實現代碼如下:
class EventBus { // 事件緩存對象 events = Object.create(null) constructor() { } // 獲取監聽器 getListeners(type) { return this.events[type] = this.events[type] || [] } // 添加監聽事件 on(type, fn) { const listeners = this.getListeners(type) // 同一個方法僅允許被添加一次 if (!listeners.includes(fn)) { listeners.push(fn) } } // 移除監聽事件 off(type, fn) { const listeners = this.getListeners(type) const index = listeners.indexOf(fn) if (index < -1) { return } else { listeners.splice(index, 1) } } // 移除所有監聽器 removeAll(type) { this.events[type] = [] } // 觸發監聽事件 fire(type, ...args) { this.getListeners(type).forEach(fn => fn(...args)) } } /** * 后台播放音頻類 */ class BGAudio extends EventBus { // 音頻標簽 audio = null // 播放音頻地址 audioUrl = null // 可以添加的有效音頻相關事件名稱 // 事件存在兼容性問題 validEvents = [ 'loadstart', // 客戶端開始請求數據 'progress', // 客戶端正在請求數據(或者說正在緩沖) 'play', // play()和autoplay播放時 'pause', // pause()方法觸發時 'ended', // 當前播放結束 'timeupdate', //當前播放時間發生改變的時候 'canplaythrough', //歌曲已經載入完全完成 'canplay', // 緩沖至目前可播放狀態 'onloadedmetadata', // 當元數據(比如分辨率和時長)被加載時 'error', // 播放出錯 ] // 播放狀態 pending(待定) playing(播放中) pausing(暫停中) playStatus = 'pending' // 待定狀態 CONSTANT = { pending: 'pending', playing: 'playing', pausing: 'pausing', } constructor(config = {}) { super() this.audioUrl = config.audioUrl this.audio = new Audio() const onEvents = config.on || {} Object.keys(onEvents).forEach((name) => { this.on(name, onEvents[name]) }) this.on('error', () => { this.stop() }) } // 是否有效事件名稱 isValidEventName(eventName) { return this.validEvents.includes(eventName) } // 添加監聽器 on(type, handler) { super.on(type, handler) this.audio.addEventListener(type, handler, false) } // 移除監聽器 off(type, handler) { this.remove(type, handler) } // 移除監聽器,當fn不存在時,移除type所有監聽器 remove(type, handler) { if (handler) { super.off(type, handler) this.audio.removeEventListener(type, handler, false) } else { this.getListeners(type).forEach((fn) => { this.audio.removeEventListener(type, fn, false) }) super.removeAll(type) } } /** * 播放相關 */ // 設置音頻地址 setAudioUrl(url) { this.audioUrl = url } // 設置播放狀態標志 setPlayStatus(status) { this.playStatus = status } // 播放,可傳遞音頻地址 play(url) { const originUrl = this.audioUrl if (url) { // url存在則使用新地址 this.setAudioUrl(url) } // 存在音頻地址才播放 if (!this.audioUrl) { return } const audio = this.audio //處於暫停狀態才需要播放 if (audio.paused) { this.setPlayStatus(this.CONSTANT.playing) // 地址變化的時候才需要重新賦值,因為重新賦值會導致刷新操作 if (originUrl !== this.audioUrl || !this.audio.src) { this.audio.src = this.audioUrl } this.audio.play() } } // 按進度播放 playByRate(playRate) { if (playRate < 0 || playRate > 100) { playRate = 0 } else if (playRate > 100) { playRate = 100 } playRate = playRate / 100 this.playByTime(this.audio.duration * playRate) } // 按時間播放 playByTime(time) { const audio = this.audio if (time < 0) { time = 0 } else if (time > audio.duration) { time = audio.duration } audio.currentTime = time this.play() } // 暫停 pause() { this.setPlayStatus(this.CONSTANT.pausing) this.audio.pause() } // 停止 stop() { this.playByTime(0) this.pause() this.setPlayStatus(this.CONSTANT.pending) } // 播放與暫停切換 togglePlay() { if (this.playStatus === this.CONSTANT.playing) { this.pause() } else { this.play() } } // 重新加載 reload() { this.setPlayStatus(this.CONSTANT.pending) this.audio.load() } }
在這里我自行實現封裝了事件接口(EventBus),實現了基本的事件發布訂閱功能,BGAudio類繼承了EventBus類,以方便對封裝的音頻類進行自定義擴展操作,當然,你也可以選擇不繼承EventBus類 ,因為獲取到的audio對象本身實現了標准瀏覽器事件接口EventTarget
音頻事件
常用音頻事件,如下圖所示

BGAudio類實現功能如下:
①,提供事件接口監聽音頻事件及html標准事件
on(type,handler) 方法添加監聽器
off(type,handler) 方法移除監聽器
fire(type,[data1,data2,...]) 方法觸發監聽器,對於自定義事件可使用該方法觸發並傳遞自定義數據,對於音頻audio原生事件使用該方法觸發無效(因為沒有event事件對象數據)
添加監聽事件可以在創建實例的時候通過參數config 的 on 字段添加 監聽事件,也可以在初始化實例后調用on方法添加,示例代碼如下:

上述兩種初始化監聽器方式實際使用時二者選一即可。
②,簡單記錄當前播放狀態信息,除了播放和暫停狀態,其他均為待定狀態 (對於錯誤狀態,后期通過自定義錯誤碼errorCode來標識錯誤,暫未實現)

③,提供音頻播放相關操作
play(url) 播放音頻
pause() 暫停播放
stop() 停止播放(即將播放進度歸零)
togglePlay() 播放與暫停之間切換
playByTime() 按照時間點進行播放
playByRate() 按照進度(0-100)播放
api僅僅提供了常用的播放操作,沒有封裝頁面樣式相關
