今天玩轉黑膠唱片,Audio Web API 接起來~~
Audio Web API 可於網頁上操作並播放音訊檔案。
根據 MDN 定義:
Web Audio API 是根據模組化路由 (Modular routing) 的概念所設計。所謂的模組化路由,即是以「音訊節點 (Audio nodes)」執行基本的音訊作業,節點又互相連接而構成「音訊路由圖 (Audio routing graphs)」。在同一環境 (Audio context) 內,又可支援數個音源與多樣的聲道配置。此模組化設計可提供更高的靈活度,並能建立複雜的音訊函式與動態效果。
設計想法:當點擊時黑膠盤開始轉動播音樂,再點擊一下暫停,另外有音量條調整音量大小。
<!-- html -->
<body>
<audio id="music" src="音源.mp3"></audio>
<h1>DROP THE MUSIC</h1>
<section>
<div id="disk" data-playing="false"></div>
<input id="volume" type="range" min="0" max="4" step="0.1" value="2" />
<label for="volume">volume</label>
</section>
</body>
CSS 的黑膠動畫效果設定
/* css */
#disk {
width: 500px;
height: 500px;
background-image: url('黑膠圖片');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
margin-bottom: 50px;
}
/* 將黑膠轉動 css 另外寫才方便 JS 套用 */
.rotating {
animation: rotate 2s linear infinite;
}
/* 動畫為黑膠從 0deg 轉動到 360deg 模擬轉動畫面 */
@keyframes rotate {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
基本設定完成,正式進入 JavaScript!
要使用 Web API 首先要創建 audioContext,可以把它想像成一個容器用來裝聲音,在裡面可以對聲音進行各種處理。
圖片來源MDN
使用建構子 AudioContext 創建
let audioCtx = new AudioContext();
在 audioContext 內需要有音源的輸入,可以是根據 url 載入的 audioNode 或者是靠 振盪器 Oscillators 產生的音源,而今天要用 HTML 標籤的<audio>
來載入音源。
使用 audioContext.createMediaElementSource(音源節點)
// 先取得 audio tag 的節點
let music = document.querySelector('#music');
// 透過剛剛創建了 audioContext 創建音源節點
let source = audioCtx.createMediaElementSource(music)
gainNode 節點是用來控制音量的大小,透過 gainNode.gain.value
可以知道目前音樂的音量,進而改變數值。
let gainNode = audioCtx.createGain();
透過 connect
將音源的輸入和輸出串連,這樣 Web API 的音源綁定就好囉~
source.connect(gainNode).connect(audioCtx.destination);
決定播放還是暫停可以設定一個屬性值 playing 做狀態轉換,當 playing = 'false'
時點擊播放,playing='true'
點擊暫停,要擷取這個屬性值當前的值使用 dataset.屬性名稱
。
如:
// html 設定 <div data-playing='false'></div>
document.querySelector('div').dataset.playing // false
點擊時透過 classList.toggle
加上 rotating class 啟動黑膠轉動
disk.addEventListener('click', function (event) {
this.classList.toggle('rotating');
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
if (this.dataset.playing === 'false') {
music.play();
this.dataset.playing = 'true';
} else if (this.dataset.playing === 'true') {
music.pause();
this.dataset.playing = 'false';
}
});
音量條的 HTML 使用 input
標籤的 type='range'
,
加上其他屬性 最小值min
、最大值max
、每次移動大小step
、預設顯示位置value
,就可以取得拉動時的 value 資訊。
監聽事件綁定 input (拉動音量條時), gainNode
節點的 value 值等同於 input
標籤上拉動的數值。
let volume = get('#volume');
volume.addEventListener('input', function (event) {
gainNode.gain.value = this.value});
MDN - AudioContext
MDN - gainNode
MDN 實作
初探 Web Audio API
Chapter1-DJ最愛的音頻動感圖像(III)媽媽叫你不要玩音樂,現在知道當DJ很難了吧
音源來源
Audio Web API 實在有太~多東西可以學了,還不知道如何取網路的 url,只能先引入本地端的 mp3 檔案,今天試試水溫!之後繼續挑戰