什么是音频可视化?
音频可视化,顾名思义,就是通过获取音频的波形、频率和其他来自音频的数据转换成图像,再到屏幕上显示出来。通过它,我们能够制作一些炫酷的前端音乐界面。
下面,我将分析一个来自云音乐技术团队的音频可视化开发案例,快速帮助小白,制作自己喜欢的炫酷的音频可视化界面。
先上图
想开发这么一个炫酷的音频界面,我们可以先来聊聊 canvas
canvas是什么
canvas是HTML5中用于图形绘制的容器元素,它通常通过JavaScript脚本来完成图形绘制。要完成我们下面的音频可视化开发,我们可以借组结构canvas的几个方法,下面将通过开发一个页面倒计时的小案例来帮助初学者了解canvas的一些属性和方法。
先上代码
<canvas id="myCanvas">
</canvas>
<script>
const canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.font = "50px Verdana";
let dis = 550;
let i = 10;
function animation(){
requestAnimationFrame(function(){
if(dis >= 0){
--dis;
if(dis%50 == 0 ){
ctx.clearRect(0,0,300,150);
ctx.fillText(i--,100,100);
}
animation();
}
});
}
animation();
</script>
我们在html
页面创建一个canvas
画布元素并设置id为myCanvas
,它的默认大小是300*150,创建好了这块画布,接下来我们就能在JavaScript脚本中绘制图形了。
先通过getElementById()
找到这个元素,然后创建canvas对象ctx
并设置填充色为红色,字体为Verdana,大小为50px,设置dis
变量用于条件控制,再定义一个i
变量用于显示倒计时数字,然后我们就可以开始在我们的画布里绘制倒计时数字了。
创建一个animation
函数,在这个函数里面,我们使用了一个html5专门用于请求动画的APIrequestAnimationFrame
请求动画帧,相比于定时器setTimeout
,它不会引起丢帧、丢帧,看起来更加流畅。
在requestAnimationFrame
里面,先设置刷帧条件dis>=0
,dis
每次减一,总共550次,再设置条件为每50次执行一次绘制操作,在每次绘制之前,通过clearRect(x,y,width,height)
方法将画布上给定矩形清空,它的4个参数分别表示要清除的矩形左上角的x,y坐标,以及要清空矩形的宽度和高度,单位以像素计算。然后再通过fillText()
画布指定位置绘制倒计时数字,该方法接收四个参数:text
输出的文本,x
绘制文本的x坐标,y
绘制文本的y坐标,注意:这两个值都是相对于画布,最后一个参数maxWidth
表示允许文本的最大宽度,它是一个可选参数。
接着我们通过递归的方式调用animation()
函数直到倒计时结束,最后在外部调用一下animation()
函数,至此,一个简单的倒计时界面完成。我们还可以给canvas
通过innerWidth
和innerHeight
设置
画布大小。
canvas
可以绘制各种图形,更多内容请自行参看canvas
内容
聊完了canvas
,接下来就是我们的正题了。
Web Audio
在开始之前,我们还需要了解什么是Web Audio。
Web Audio 是 Web 端处理和分析音频的一套 API 。它可以使用户在音频上下文中进行音频操作,具有模块化路由的特点,它也使我们能够控制音频的空间化。
通过Web Audio,我们能够实现取数据和映射数据两个过程,下面我们将实现这两个过程。
项目实现
我们先在页面创建一个canvas
元素和一个audio
标签以及一个用于作播放按钮的a
标签。
然后在JavaScript里面获取audio
和a
这两个元素,并给a
标签设置单击事件。
var btn = document.getElementById('play-btn');
var audio = document.getElementById('audio');
btn.addEventListener('click',function(){
btn.style.display = 'none';
audio.play();
onloadAudio();
})
在onLoadAudio()
函数里面,我们先获取canvas
元素,设置它占满整个页面,再创建canvas
的对象。
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext('2d');
创建 **AudioContext **对象,用来控制它所包含的节点的创建,以及音频处理、解码操作的执行。
var audioCtx = new (window.AudioContext || window.webkitAud
ioContext)();
通过createAnalyser()
方法创建 **AnalyserNode **用来获取音频时间和频率数据,实现音频数据可视化。
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 512;
fftSize 在 MDN 里面介绍是快速傅里叶变换的一个参数,取值必须是从32到32768范围内的2的非零幂,默认值为2048,在这里我们取512。另外,fftSize 的值决定了 frequencyData 的长度。
将音频节点关联到 AudioContext上,作为整个音频分析的输入。
我们采用MediaElementAudioSourceNode 将<audio>
节点作为输入源,并将音频关联到分析器,再将分析器关联到输出设备。
var source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
接下来获取频率数组。
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
frequencyBinCount()
的值是 fftSize 取值的一半,所以这里的 Uint8Array() 数组的长度就是256。
然后设置音柱的宽度,而高度只定义变量而不赋值,留在后面通过dataArray[]
数组动态设置
var barWidth = WIDTH / bufferLength*1.5;
var barHeight;
绘制音柱
定义一个 renderFrame()
函数用于绘制音柱,并且每次绘制之前都先将整个画布清除,然后更新频率数组。
ctx.clearRect(0,0,WIDTH,HEIGHT);
analyser.getByteFrequencyData(dataArray);
通过for
循环里面设置每一个矩形的高度,再根据高度设置一个背景色,然后绘制矩形,并填充背景颜色。然后通过递归的方式调用函数。
barHeight = dataArray[i];
var r = barHeight + 25 * (i / bufferLength);
var g = 250 * (i / bufferLength);
var b = 50;
ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(x,HEIGHT-barHeight,barWidth,barHeight);
x += barWidth+2;
最后,运行代码,体验属于你的可视化音乐吧。
小结
本文简单介绍了 canvas 的使用和如何通过 Web Audio 的相关 API 获取音频的频率数据。
然而 canvas
和 Web Audio
的用处远远不止于此,读者还可以发挥想象力和创造力,开发出更多有意思的项目。