Skip to content
Kiwi edited this page Apr 19, 2015 · 5 revisions

事件的监听

所有的对外公开的事件都绑定到 MuPlayer 的实例上,会在特定时机自动派发。开发者可根据业务需要,监听对应的事件类型并做出处理。MuPlayer 项目使用了 arale 的事件库,暴露的事件监听绑定与解绑的方法有 ononceoff

on object.on(event, callback, [context])

用于在 muplayer 上监听对应名称的事件,当事件派发时触发回调。 参考:http://aralejs.org/events/#on-object-on-event-callback-context

var muplayer = new _mu.MuPlayer();
muplayer.on('playing', function() {
    console.log('muplayer播放时被调用');
});

once object.once(event, callback, [context])

作用同 on,但只监听一次,即事件触发回调后自动解绑。

off object.off(event, callback, [context])

用于解绑事件监听,调用 off 意味着不再监听之前通过 on 方法绑定的事件及监听回调。 参考:http://aralejs.org/events/#off-object-off-event-callback-context

常用事件

播放事件的派发时机大致有两类:

  • 播放状态切换时会派发对应的状态事件,这些状态被定义在了 cfg.cofeeSTATES 常量中:
STATES:
	CANPLAYTHROUGH: 'canplaythrough'
	PREBUFFER: 'waiting'
	BUFFERING: 'loadeddata'
	PLAYING: 'playing'
	PAUSE: 'pause'
	STOP: 'suspend'
	END: 'ended'
  • 会连续间隔派发的播放事件,如表征播放进度的 timeupdate 和表征加载进度的 progress

MuPlayer 播放相关的事件原则上维持了和HTML5 Audio规范的统一,但做了相应的简化,并非面面俱到。下面分别列举下常见的播放事件:

player:#{fn_name}

首先明确下,muplayer 中定义了一些自定义事件,当实例方法被调用后会立即派发对应方法名且有 player 前缀的对应事件。如,play 方法被调用后,会立即派发 player:play 事件;stop 方法被调用后,会立即派发 player:stop 事件。这些事件并不代表真正的播放状态,即派发了 player:play 事件,只代表 play 方法被调用,但不代表 muplayer 处于 playing 状态。好处是,这些事件可以当做一个及时事件使用(避免异步事件回调事件的不确定性),如后面举例的播放按钮的状态渲染,就依赖了 player:play 事件。

playing

歌曲播放时,muplayer 会 trigger playing 事件。因此,要获得歌曲播放的时机,需主动监听 playing 事件。

pause

歌曲暂停时(主动调用 pause 方法后),muplayer 会暂停播放并派发 pause 事件。

suspend

歌曲停止时(与暂停的区别是停止播放会将播放位置重置会0,即再次播放,会从歌曲头部开始播放),muplayer 会停止播放并派发 suspend 事件。

关于 playingpausesuspend 事件的一个常见使用案例是,根据播放状态改变按钮的状态 icon。这里需要注意的是,这三个状态事件的派发都是异步的(尤其是 playing 事件,因为还要加载并准备音频资源,会有一定延迟),并不是点击按钮后立即就派发对应的事件,如果仅监听事件再改变按钮 icon,虽然可以保证播放状态的一致性,但用户会感觉到明显的延迟卡顿。因此常见做法是,按钮按下时,立即改变按钮 icon,并调用对应播放/暂停方法,同时监听 pause 和 suspend 事件,当播放停止时,因触发对应的 pause 或 suspend 回调,将按钮icon重置。为了保证playing 切换的即时性,可以监听 player:play 方法。代码如下:

$ctrlBtn.click(function() {
    if ($ctrlBtn.hasClass('play-icon')) {
        $ctrlBtn.removeClass('play-icon');
        player.play();
    } else {
        $ctrlBtn.addClass('play-icon');
        player.pause();
    }
});

muplayer.on('pause suspend', function() {
    $ctrlBtn.addClass('play-icon');
}).on('player:play', function() {
    $ctrlBtn.removeClass('play-icon');
});

ended

一首歌播放完成后会派发 ended 事件。通常,这个事件无需主动监听,因为 muplayer 在一首歌播完后会主动监听 ended 事件,并调用 next 方法自动切歌。但如果有其他业务需求,如完整播放次数统计等,也可以自己监听 ended 事件并实现对应的统计代码。

timeupdate

muplayer 播放时,会持续派发 timeupdate 事件,并将当前播放进度(单位毫秒)传递给监听的回调方法。

muplayer.on('timeupdate', function(pos) {
    // pos单位是毫秒,表示当前播放的进度是多少毫秒。
    // 此处也可以通过 muplayer.curPos(true) 方法获得格式化后的播放进度。 
});

progress

muplayer 加载音频时,会持续派发 progress 事件,并将当前的加载进度(0 - 1以内的浮点数)传递给监听的回调方法。

muplayer.on('progress', function(progress) {
    // progress为0 - 1以内的浮点数,表示当前音频资源的缓冲进度。
});

canplaythrough

音频加载完成(即加载进度达到100%)时,muplayer 会派发 canplaythrough 事件。

error

muplayer 播放出错时(如网络中断导致的资源加载错误),会尽可能捕获异常,并抛出error事件。一般而言,调用者不需要自己处理 error,但为了记录错误日志,还是将这个事件暴露了出来。

player:statechange

muplayer 播放状态改变时,都会派发 player:statechange 事件,事件参数有 newStateoldState 两个参数,分别代表状态改变时的新状态(当前状态)和之前状态。

player:waiting_timeout

当播放出现卡断(即超过预设的 maxWaitingTime 依然播放停滞时),会派发 player:waiting_timeout 事件,供开发者自行处理(继续等待、重试或切歌?)。