實現思路
-
原生的audio標簽,controls屬性用於控制是否顯示一個默認的播放器,這個播放器的樣式是瀏覽器決定的,如果使用默認播放器,在不同的瀏覽器中呈現的樣式會不一樣。要實現自定義播放器樣式,就不要去設置control(因為controls默認值為false)。
-
通過監聽原生audio標簽的事件,以及調用原生audio標簽的方法,來實現對音頻的控制。自定義播放器只是一個軀殼,本質的操作全在audio標簽上。
-
因為該vue項目使用了vant,中間的滑條就直接使用了vant的slider組件。當然,也可以使用vue-slider-component組件,或者自己手寫一個小輪子。
-
用動作去更新狀態。而不是先更新狀態,再監聽狀態變更去執行動作。因為動作執行不一定會成功,如果狀態跟執行結果不一樣就很尷尬了。
效果預覽
(看起來非常簡單,或者說簡陋,因為平時對audio並沒有什么接觸,此文僅作筆記之用。)
audio的常用的屬性
controls
。如果聲明了該屬性,瀏覽器將提供一個包含聲音,播放進度,播放暫停的控制面板,樣式由瀏覽器決定。currentTime
。當前音頻已播放時長。duration
。當前音頻總時長。preload
。預加載,這是一個枚舉屬性,none
表示不做預加載,metadata
表示會對元數據(比如音頻時長)做預加載,auto
表示會嘗試對元數據以及音頻柳做完全預加載。src
。音頻文件的地址。playbackRate
。播放速度。網上常見的1x
,1.5x
,0.5x
播放速度就是利用該屬性實現的。
audio的常用的事件
loadedmetadata
。表示音頻元數據已經被加載,我們一般在這里通過event.target.duration
獲取音頻總時長。canplay
。這個事件會在loadedmetadata
之后觸發,表示音頻可以被播放了。canplaythrough
。這個事件會在canplay
之后觸發,表示瀏覽器認為不出意外的話音頻可以被播到最后。play
。表示音頻已開始播放。pause
。表示音頻已暫停播放。ended
。表示播放完了最后一幀。error
。表示播放出錯,可能是音頻文件地址無效,或者音頻格式不支持。timeupdate
。表示正在播放中,播放過程中會被頻繁觸發,一般在這里通過event.target.currentTime
來實時獲取已播放時長。
audio的常用的方法
play
。播放音頻。此方法會返回一個Promise
對象。不需要音頻數據已經加載到能夠播放的狀態。如果錄音文件地址可用,會走到fulfilled
狀態;如果錄音文件地址不可用或者缺失,會走到rejected
狀態;pause
。暫停音頻。返回值和行為均與play
一樣。
常用場景實現
1,顯示音頻時長如何實現?
答:監聽loadedmetadata
,通過event.target.duration
取出音頻總時長,因為音頻總時長單位為秒,所以一般情況下都會有一個秒轉換為時分秒格式的需求,而且一般情況下還要補0,實現如下:
const filterDuration = (s=0) => {
if (typeof s !== 'number') {
throw new Error('傳入時長需為數字類型')
};
let hour = Math.floor(s / 3600);
let min = Math.floor((s % 3600) / 60);
let sec = Math.floor(s % 60);
hour = hour < 10 ? `0${hour}` : hour;
min = min < 10 ? `0${min}` : min;
sec = sec < 10 ? `0${sec}` : sec;
return `${hour}:${min}:${sec}`;
}
2,如何動態獲取當前播放百分比?
答:監聽timeupdate
事件,通過event.target.currentTime / event.target.duration
來計算百分比。這里我遇到了一個比較奇特的問題:當音頻時長很短時(比如只有幾秒鍾),有時候event.target.currentTime
會大於音頻總時長。所以我針對播放進度百分比大於100%的情況做了處理,目前不是太明白該現象原因所在。
寫在最后
這只是對audio標簽的一個入門使用,實際上我對audio了解得並不多,特此記錄一些基礎操作,方便后續自己翻閱。