1、最终效果
2、代码思路
3、相关问题
1)出于功能需要,当使用audioObj.play()播放歌曲时,想通过duration属性获取歌曲的总时长,但总返回NaN。
这是因为刚开始播放时,歌曲的各项属性信息还未加载到,所以需要在初始时为audioObj绑定事件监听,按照audio提供的方法,在loadedmetadata事件触发时,音乐的各项参数都会加载完。
this.audioObj.onloadedmetadata=function(){
_this.duration=_this.audioObj.duration;
_this.play();
};
2)当音乐播放完成时,需要执行一些操作。audio提供了两种方法(ended方法和ended属性),用哪种好呢?
自然是ended方法。起先因为要用计时器不断获取currentTime,我就想直接在计时器里顺便监测ended属性,但是因为计时器是每秒执行一次,所以可以明显看到界面上的文字图片都已经切换到下一首了,而滑块还会在进度条尾部停滞一下才跳回去。
3)还有一点值得注意,如果在进度条上绑定click事件以便调节音乐播放进度,需要在子元素上阻止冒泡(我的滑块和时间戳都在进度条内)。
因为我是用vue编写,所以比较简单,只需给滑块和时间戳添加@click.stop即可。
4、代码优化
1)在点击“上一首”、“下一首”按钮切歌时,需要确保序号不越界,起点最低被想到的是逻辑观感比较好理解的if语句,但它的代码观感却令人不爽。
① 如果是非循环播放,可使用Math.max和Math.min方法:
this.index = Math.max(--this.index,0);
this.index = Math.min(++this.index,this.total-1);
② 如果是循环播放,可使用取余法:
this.index =(--this.index+this.total)%this.total;
this.index = ++this.index%this.total;
2)在切换“播放/暂停”时,往往也最容易想到if判断,但我觉得用三目代码更优雅一些。
this.playing?this.pause():this.play();
Github下载链接:音乐播放器