我們經常看到在聽樂音的時候,會有音譜圖隨著音樂的節奏不斷變化給人視覺上的享受,那麼我們通過js來實現以下這個效果,下面是簡單的效果圖
首先我們需要有一個繪製音訊的函數
function draw() {
// 請求下一幀動畫
animationId = requestAnimationFrame(draw);
// 獲取音訊頻譜資料
analyser.getByteFrequencyData(dataArray);
// 清空畫布
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 計算每個頻譜條的寬度
var barWidth = (canvas.width / bufferLength) * 2.5;
var barHeight;
var x = 0;
// 遍歷頻譜資料陣列,繪製頻譜條
for (var i = 0; i < bufferLength; i++) {
// 計算頻譜條的高度
barHeight = dataArray[i] / 255 * canvas.height;
// 根據頻譜條的索引值計算顏色(彩虹色)
var hue = i / bufferLength * 360;
ctx.fillStyle = 'hsl(' + hue + ', 100%, 50%)';
// 繪製頻譜條矩形
ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
// 更新下一個頻譜條的起始位置
x += barWidth + 1;
}
}
這個函數是用於繪製頻譜圖的核心部分。它使用requestAnimationFrame()
方法來請求下一幀動畫,並將自身作為回撥函數。這樣可以不斷更新頻譜圖。
在函數內部,analyser.getByteFrequencyData(dataArray)
用於獲取當前的音訊頻譜資料,將資料儲存在dataArray
陣列中。
然後,畫布被清空,使用黑色填充整個畫布。
接下來,通過計算每個頻譜條的寬度,以及根據頻譜資料計算每個頻譜條的高度,來確定頻譜條的繪製引數。
然後,使用彩虹色調的漸變來設定頻譜條的顏色,顏色的HSL值根據頻譜條的索引值計算。
最後,在畫布上繪製每個頻譜條的矩形,每個矩形之間留有間距。
通過不斷呼叫requestAnimationFrame()
方法並在每一幀更新頻譜圖,可以實現連續的動畫效果。
document.getElementById('playButton').addEventListener('click', function() { if (!audioContext) { audioContext = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; audioElement = document.createElement('audio'); audioElement.src = '1.mp3'; audioElement.controls = true; audioElement.style.display = 'none'; document.body.appendChild(audioElement); var source = audioContext.createMediaElementSource(audioElement); source.connect(analyser); analyser.connect(audioContext.destination); bufferLength = analyser.frequencyBinCount; dataArray = new Uint8Array(bufferLength); } audioElement.play(); draw(); }); document.getElementById('pauseButton').addEventListener('click', function() { audioElement.pause(); cancelAnimationFrame(animationId); });
當用戶點選"播放"按鈕時,建立一個新的AudioContext
物件用於處理音訊,建立一個AnalyserNode
物件用於分析音訊頻譜。然後建立一個audio
元素並將其設定為要播放的音訊檔。將audio
元素連線到AnalyserNode
,將AnalyserNode
連線到AudioContext
的目標(通常是揚聲器)。設定頻率分析器的引數,包括FFT大小。
當用戶點選"播放"按鈕時,音訊開始播放,並且在draw()
函數中的requestAnimationFrame(draw)
中呼叫的迴圈中,更新頻譜資料並繪製頻譜圖。首先,使用analyser.getByteFrequencyData(dataArray)
獲取音訊頻譜資料。然後,通過遍歷資料陣列,計算每個頻譜條的高度,並根據頻譜條的位置在畫布上繪製矩形。顏色根據頻譜條的索引值計算,使得頻譜圖呈現彩虹色的效果。
當用戶點選"暫停"按鈕時,音訊暫停播放,並呼叫cancelAnimationFrame(animationId)
來停止繪製頻譜圖。
請確保將audioElement.src
中的路徑替換為你要播放的實際音訊檔的路徑。
當然修改draw函數可以得到其他的音訊圖,比如波形圖
具體的draw程式碼如下
這個函數主要用於繪製音訊的時域波形圖。它也使用了requestAnimationFrame()
方法來請求下一幀動畫,並將自身作為回撥函數。
在函數內部,analyser.getByteTimeDomainData(dataArray)
用於獲取當前的音訊時域資料,將資料儲存在dataArray
陣列中。
然後,畫布被清空,並將背景顏色設定為lime。
接下來,設定線條的寬度和顏色。
然後,開始繪製路徑。
通過計算每個資料片段的寬度,以及根據時域資料計算每個點的縱座標,確定波形圖的繪製引數。
然後,根據波形點的位置,使用moveTo()
方法將繪製路徑移動到第一個點的位置,並使用lineTo()
方法連線到下一個點的位置。這樣就形成了一條完整的波形路徑。
在遍歷完所有的資料點後,使用lineTo()
方法將最後一個點連線到畫布的右側中點,以形成閉合路徑。
最後,使用stroke()
方法繪製路徑。
通過不斷呼叫requestAnimationFrame()
方法並在每一幀更新波形圖,可以實現連續的動畫效果。