馬上又要開學了😭😭😭。
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
的順序進行執行。