iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
Modern Web

舌尖上的JS系列 第 28

D28 - 走!去瀏覽器玩轉黑膠唱片 Web Audio API

前言

今天玩轉黑膠唱片,Audio Web API 接起來~~

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

1. 第一步:建立 AudioContext

要使用 Web API 首先要創建 audioContext,可以把它想像成一個容器用來裝聲音,在裡面可以對聲音進行各種處理。


圖片來源MDN

使用建構子 AudioContext 創建

   let audioCtx = new AudioContext();

2. 第二步:建立音源節點

audioContext 內需要有音源的輸入,可以是根據 url 載入的 audioNode 或者是靠 振盪器 Oscillators 產生的音源,而今天要用 HTML 標籤的<audio> 來載入音源。

使用 audioContext.createMediaElementSource(音源節點)

// 先取得 audio tag 的節點
let music = document.querySelector('#music');

// 透過剛剛創建了 audioContext 創建音源節點
let source = audioCtx.createMediaElementSource(music)

3. 第三步: 建立 gainNode 音量節點

gainNode 節點是用來控制音量的大小,透過 gainNode.gain.value 可以知道目前音樂的音量,進而改變數值。

let gainNode = audioCtx.createGain();

4. 第四步:建立連結 connect

透過 connect 將音源的輸入和輸出串連,這樣 Web API 的音源綁定就好囉~

source.connect(gainNode).connect(audioCtx.destination);

5. 第五步:設定黑膠點擊事件

決定播放還是暫停可以設定一個屬性值 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';
    }
});

6. 第六步:設定音量條

音量條的 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});

完成

Reference

MDN - AudioContext
MDN - gainNode
MDN 實作
初探 Web Audio API
Chapter1-DJ最愛的音頻動感圖像(III)媽媽叫你不要玩音樂,現在知道當DJ很難了吧
音源來源

結語

Audio Web API 實在有太~多東西可以學了,還不知道如何取網路的 url,只能先引入本地端的 mp3 檔案,今天試試水溫!之後繼續挑戰
/images/emoticon/emoticon08.gif


上一篇
D27 - 走!去瀏覽器學 Drag & Drop 自己組漢堡包
下一篇
D29 - 走!去瀏覽器自己刻表單選 pizza 口味
系列文
舌尖上的JS30

2 則留言

0
Chiahsuan
iT邦新手 5 級 ‧ 2021-10-13 22:16:31

我之後也要玩玩看~~~音樂選得好/images/emoticon/emoticon24.gif

0
juck30808
iT邦新手 3 級 ‧ 2021-10-14 12:12:24

恭喜即將邁入完賽~/images/emoticon/emoticon08.gif

我要留言

立即登入留言