js 實現原生 Audio 初探版
再也不用擔心面試問到H5用到哪些新元素了,大神如我 小弟用js原生實現了 抄了 Audio,Video還會遠嗎?
本專案基於 ES6+scss+webpack 開發的原生 JS 版 H5 Audio
,此次分享的目的是讓前端對 H5 的 Audio 有更深的瞭解,同時對現代前端技術也有個大致的瞭解,最終可以基於 vue
或 react
開發一個 H5 版的 網易音樂,QQ 音樂...
由於工作中有音訊方面的需求,所以該專案也是自己作為迭代的記錄。意味著,這將是一個系列教程。
教程
實現原生音訊無外乎兩個部分
首先要先了解 Aduio
的屬性和方法。
關於 Audio 元素的介紹,推薦 MDN
UI
首先原生 audio 元素是必不可少的,我們也可以直接新增 controls
屬性來使用瀏覽器實現的 UI。
<audio id="myaudio" src="/static/test.mp3" controls></audio>
複製程式碼
基礎的 DOM 結構應該包括:
- 播放按鈕
- 進度條
- 聲音控制
- 當前時間/總時長
總體結構建議使用語義化元素,樣式類名命名參考BEM
。音訊建議考慮 視覺障礙者
,可引入 無障礙
這邊簡單講一下進度條
的實現。通過 input
型別中 range
和 progress
可以大大降低 DOM 結構複雜度及提高語義化。
其中涉及到改瀏覽器原生樣式讀者可自行谷歌。也可以參考本專案原始碼
<div class="myaudio__controls">
<button type="button" data-myaudio="play"></button>
<span class="myaudio__progress">
<input class="myaudio__progress--seek" type="range" min="0" max="100" step="0.1" value="0" data-myaudio="seek">
<progress class="myaudio__progress--played" max="100" value="0" role="presentation"></progress>
<progress class="myaudio__progress--buffer" max="100" value="20.43"></progress>
</span>
<span class="myaudio__time--current">00:00</span>
<span class="myaudio__time--duration">00:20</span>
<button type="button" data-myaudio="mute"></button>
<span class="myaudio__volume">
<input class="myaudio__volume--input" type="range" min="0" max="10" value="10" data-myaudio="volume">
<progress class="myaudio__volume--display" max="10" value="10" role="presentation">
</progress>
</span>
</div>
複製程式碼
Event
事件與 DOM 元素密不可分,而音訊主要分兩個方向去監聽事件。使用者自定義的 DOM 元素事件監聽,Audio 原生事件監聽。涉及的知識點是 addEventListenter
和 自定義事件
。
本次 Audio 外掛基於 Es6 的 class
開發。最終可以直接通過 例項化來生成一個 audio
物件
我們先從配置檔案來大致瞭解下開發一個 Audio 所用到的配置項。
export default {
// 配置對應功能
controls: ['play', 'progress', 'current-time', 'duration', 'mute', 'volume'],
// 基於iconfont,SVG版,如需替換圖片,
// 可直接匯入自己的iconfont檔案,修改對應圖片類名即可
icon: {
play: 'icon-bofang',
pause: 'icon-bofangzanting',
muted: 'icon-jingyin',
volume: 'icon-shengyin'
},
// 配置是否自動播放
autoplay: false,
// 聲音控制相關
volumeMin: 0,
volumeMax: 10,
volume: 10,
// 播放器HTML結構
html: '',
// Debugger 相關
logPrefix: '日誌:',
debug: true,
// 整體思路是通過控制全域性狀態類名,來設定對應樣式
classes: {
setup: 'myaudio--setup',
ready: 'myaudio--ready',
stopped: 'myaudio--stopped',
playing: 'myaudio--playing',
muted: 'myaudio--muted',
loading: 'myaudio--loading',
hover: 'myaudio--hover',
isIos: 'myaudio--is-ios',
isTouch: 'myaudio--is-touch'
},
// 狀態儲存相關
storage: {
enabled: true,
key: 'myaudio'
},
// 選擇器相關
selectors: {
container: '.myaudio',
controls: {
container: null,
wrapper: '.myaudio__controls'
},
labels: '[data-myaudio]',
buttons: {
seek: '[data-myaudio="seek"]',
play: '[data-myaudio="play"]',
pause: '[data-myaudio="pause"]',
mute: '[data-myaudio="mute"]'
},
volume: {
input: '[data-myaudio="volume"]',
display: '.myaudio__volume--display'
},
progress: {
container: '.myaudio__progress',
buffer: '.myaudio__progress--buffer',
played: '.myaudio__progress--played'
},
currentTime: '.myaudio__time--current',
duration: '.myaudio__time--duration'
},
// 主要功能涉及以下 5 個事件
// 事件相關
listeners: {
seek: null,
play: null,
pause: null,
mute: null,
volume: null
}
};
複製程式碼
從配置檔案可以大概瞭解總體思路。下次分享將從原始碼解析的角度進一步講解 Audio 原生實現。
其他分享
以下推薦閱讀,讀者可選讀:
快速執行
在前端的世界裡,所碼即所得。當我想要了解一個專案的時候,我會直接執行看效果。
接下來,假設你已經具備一定的前端工程化開發經驗。
cd ~/Desktop
git clone https://github.com/leer0911/myAudio.git
cd myAudio
npm i
npm run dev
複製程式碼
參考
感謝 plyr,可以說本教程是對它的一次原始碼解析。