import getRealPath from 'uni-platform/helpers/get-real-path'
|
|
/**
|
* 可以批量设置的监听事件
|
*/
|
const innerAudioContextEventNames = ['onCanplay', 'onPlay', 'onPause', 'onStop', 'onEnded', 'onTimeUpdate', 'onError', 'onWaiting', 'onSeeking', 'onSeeked']
|
|
const innerAudioContextOffEventNames = ['offCanplay', 'offPlay', 'offPause', 'offStop', 'offEnded', 'offTimeUpdate', 'offError', 'offWaiting', 'offSeeking', 'offSeeked']
|
|
/**
|
* 音频上下文对象
|
*/
|
class InnerAudioContext {
|
/**
|
* 原始音频对象
|
*/
|
_audio
|
/**
|
* 是否暂停中
|
*/
|
_stoping
|
/**
|
* 开始时间
|
*/
|
startTime
|
/**
|
* 事件监听
|
*/
|
_events
|
/**
|
* 音频地址
|
*/
|
_src
|
/**
|
* 音频上下文初始化
|
*/
|
constructor () {
|
var audio = this._audio = new Audio()
|
this._stoping = false
|
// 和audio对象同名同效果的属性
|
var propertys = ['src', 'autoplay', 'loop', 'duration', 'currentTime', 'paused', 'volume']
|
propertys.forEach((property) => {
|
Object.defineProperty(this, property, {
|
set: property === 'src' ? (src) => {
|
audio.src = getRealPath(src)
|
this._src = src
|
return src
|
} : (val) => {
|
audio[property] = val
|
return val
|
},
|
get: property === 'src' ? () => {
|
return this._src
|
} : () => {
|
return audio[property]
|
}
|
})
|
})
|
this.startTime = 0
|
Object.defineProperty(this, 'obeyMuteSwitch', {
|
set (val) {
|
return false
|
},
|
get () {
|
return false
|
}
|
})
|
Object.defineProperty(this, 'buffered', {
|
get () {
|
var buffered = audio.buffered
|
if (buffered.length) {
|
return buffered.end(buffered.length - 1)
|
} else {
|
return 0
|
}
|
}
|
})
|
// 初始化事件监听列表
|
this._events = {}
|
innerAudioContextEventNames.forEach(eventName => {
|
this._events[eventName] = []
|
})
|
audio.addEventListener('loadedmetadata', () => {
|
var startTime = Number(this.startTime) || 0
|
if (startTime > 0) {
|
audio.currentTime = startTime
|
}
|
})
|
// 和audio对象同名同效果的事件
|
var eventNames = ['canplay', 'play', 'pause', 'ended', 'timeUpdate', 'error', 'waiting', 'seeking', 'seeked']
|
var stopEventNames = ['canplay', 'pause', 'seeking', 'seeked', 'timeUpdate']
|
eventNames.forEach(eventName => {
|
audio.addEventListener(eventName.toLowerCase(), () => {
|
// stop事件过滤
|
if (this._stoping && stopEventNames.indexOf(eventName) >= 0) {
|
return
|
}
|
this._events[`on${eventName.substr(0, 1).toUpperCase()}${eventName.substr(1)}`].forEach((callback) => {
|
callback()
|
})
|
}, false)
|
})
|
}
|
|
/**
|
* 播放
|
*/
|
play () {
|
this._stoping = false
|
this._audio.play()
|
}
|
|
/**
|
* 暂停
|
*/
|
pause () {
|
this._audio.pause()
|
}
|
|
/**
|
* 停止
|
*/
|
stop () {
|
this._stoping = true
|
this._audio.pause()
|
this._audio.currentTime = 0
|
this._events.onStop.forEach((callback) => {
|
callback()
|
})
|
}
|
|
/**
|
* 跳转到
|
* @param {number} position
|
*/
|
seek (position) {
|
this._stoping = false
|
position = Number(position)
|
if (typeof position === 'number' && !isNaN(position)) {
|
this._audio.currentTime = position
|
}
|
}
|
|
/**
|
* 销毁
|
*/
|
destroy () {
|
this.stop()
|
}
|
}
|
|
// 批量设置音频上下文事件监听方法
|
innerAudioContextEventNames.forEach((eventName) => {
|
InnerAudioContext.prototype[eventName] = function (callback) {
|
if (typeof callback === 'function') {
|
this._events[eventName].push(callback)
|
}
|
}
|
})
|
|
// 批量设置音频上下文事件取消监听方法
|
innerAudioContextOffEventNames.forEach((eventName) => {
|
InnerAudioContext.prototype[eventName] = function (callback) {
|
var handle = this._events[eventName.replace('off', 'on')]
|
var index = handle.indexOf(callback)
|
if (index >= 0) {
|
handle.splice(index, 1)
|
}
|
}
|
})
|
|
/**
|
* 创建音频上下文
|
*/
|
export function createInnerAudioContext () {
|
return new InnerAudioContext()
|
}
|