马上又要开学了😭😭😭。
1. 前言#
我在为我的博客实现一个移动端使用的音乐播放器的时候,为了美观,我们不得通过调用audio
的api
来实现自己想要的样式,那么我们在使用他们的时候应该注意些什么呢。
2.audio 的使用方法#
要想了解它我们就应该知道它怎样被使用,下面是它的基本使用,有两种方式:
-
直接使用
audio
标签。这里我是使用的vue
来动态的切换播放的音乐。<audio :src="currentMusic.url" controls @ended="musicEnd" ref="myaudio" style="display:none;"> 您的浏览器不支持audio </audio>
以上代码就是通过修改
src
来切换音频的播放,但是这里要注意几点:- 以这种方式来切换音频是不需要调用
this.$refs.myaudio.load()
方法,它会自动的加载音频,,这是因为在 vue 中如果改变某个属性,那么将会引起浏览器的重排,从而会使浏览器自动的去获取音频数据。 - 每次只有一个音频,可能会遇到浏览器不兼容的情况。
- 如果直接使用
this.$refs.myaudio.play()
可能会出现音频还没加载好你就调用这个方法来播放,在显然是不合理的。
- 以这种方式来切换音频是不需要调用
-
使用
source
的方式。<audio controls> <source id='test' src="http://music.163.com/song/media/outer/url?id=26447698.mp3" type="audio/mpeg"> <source src="horse.ogg" type="audio/ogg"> 您的浏览器不支持 audio 元素。 </audio>
使用上面的这种方式可以通过添加多个
source
标签来实现对不同浏览器的格式兼容问题。其余的和第一种方式类似。
3. 关于在什么时候调用 play 方法#
如果你是直接在切换了src
后调用play
方法来播放,那么这样很有可能出现问题,例如这是一个切换下一首的方法:
next(){
this.currentMusic = this.audio[this.current+1 === this.allMusic?this.current = 0:++this.current]
this.$refs.myaudio.play()
}
},
currentMusic
表示当前的音乐,current
为当前音乐的索引值,allMusic
为总的音乐数量,audio
为全部音乐的列表,在点击下一首时会调用这个方法,因为这是使用 vue,所以每次切换src
后,audio
会重新加载,但是如果我们点击的过快,或者是网速过慢,那么将会出现一个错误。
DOMException: The play() request was interrupted by a new load request.
关于这个错误正如字面的意思一样,资源还没有准备好,你就开始播放了,这显然是错误的行为,那么如何解决这个问题呢?我们很快就能想到,如果我知道了资源准备好了,再去调用这个 play 方法来进行播放不久行了吗。当然正如你所见,HTML5
提供了这些方法。
4. 怎样确定使用 play 方法的时机#
为了确定audio
的数据是否加载好了我们可以通过在视频 / 音频(audio/video)加载过程中,会触发一个事件oncanplay
来通知你视频 / 音频已经可以播放了,用法如下:
this.currentMusic = this.audio[this.current - 1 === -1?this.current =this.allMusic - 1:--this.current]
this.$refs.myaudio.oncanplay =()=>{
this.$refs.myaudio.play();
}
在切换完音频后,audio
先会自动的加载音频,当加载完毕后会触发oncanplay
来执行你想要的操作。
除了这一个事件对象,相应的还有onloadstart
,ondurationchange
,onloadedmetadata
,onloadeddata
,onprogress
,oncanplaythrough
// onloadstart 事件在浏览器开始寻找指定视频/音频(audio/video)触发。
audio.onloadstart = function (){
console.log('开始寻找指定视频/音频')
}
// ondurationchange 事件在视频/音频(audio/video)的时长发生变化时触发
// 注意:当视频/音频(audio/video)已经加载后,视频/音频(audio/video)的时长从 "NaN" 修改为正在的时长。
audio.ondurationchange = function (){
console.log('视频/音频(audio/video)发生了改变')
}
// onloadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发
// 注意:视频/音频(audio/video)的元数据包含: 时长,尺寸大小(视频),文本轨道。
audio.onloadedmetadata = function (){
console.log('视频/音频(audio/video)的元数据被加载')
}
// onloadeddata 事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的下一帧时触发。
audio.onloadeddata = function (){
console.log('当前帧的数据已经加载完成了,但是下一帧还有加载好')
}
// onprogress 事件在浏览器下载指定的视频/音频(audio/video)时触发。
audio.onprogress = function (){
console.log('(audio/video)开始下载了')
}
// oncanplay 事件在用户可以开始播放视频/音频(audio/video)时触发。
audio.oncanplay = function (){
console.log('我现在可以播放了')
}
// oncanplaythrough 事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。
audio.oncanplaythrough = function (){
console.log('视频/音频(audio/video)已经全部加载完了')
}
以上的这些事件都会在播放视频 / 音频(audio/video)过程中触发,他们会按照onloadstart
,ondurationchange
,onloadedmetadata
,onloadeddata
,onprogress
,oncanplay``oncanplaythrough
的顺序进行执行。