使用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仅仅提供了常用的播放操作,没有封装页面样式相关