基于JavaScript实现简单的音乐音谱图效果
作者:小不点灬
我们经常看到在听乐音的时候,会有音谱图随着音乐的节奏不断变化给人视觉上的享受,那么我们通过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()
方法并在每一帧更新波形图,可以实现连续的动画效果。
function draw() { // 请求下一帧动画 animationId = requestAnimationFrame(draw); // 获取音频时域数据 analyser.getByteTimeDomainData(dataArray); // 清空画布并设置背景颜色为lime ctx.fillStyle = 'lime'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 设置线条宽度和颜色 ctx.lineWidth = 2; ctx.strokeStyle = 'black'; // 开始绘制路径 ctx.beginPath(); // 计算每个数据片段的宽度 var sliceWidth = canvas.width * 1.0 / bufferLength; var x = 0; // 遍历时域数据数组,绘制波形 for (var i = 0; i < bufferLength; i++) { // 将数据归一化到范围[-1, 1] var v = dataArray[i] / 128.0; // 计算波形点的纵坐标 var y = v * canvas.height / 2; if (i === 0) { // 移动到第一个点的位置 ctx.moveTo(x, y); } else { // 连接到下一个点的位置 ctx.lineTo(x, y); } // 更新下一个点的横坐标 x += sliceWidth; } // 连接最后一个点到画布右侧中点,形成闭合路径 ctx.lineTo(canvas.width, canvas.height / 2); // 绘制路径 ctx.stroke(); }
到此这篇关于基于JavaScript实现简单的音乐音谱图效果的文章就介绍到这了,更多相关JavaScript音谱图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!