快速上手网易云音乐可视化

10,084 阅读5分钟

什么是音频可视化

音频可视化,顾名思义,就是通过获取音频的波形、频率和其他来自音频的数据转换成图像,再到屏幕上显示出来。通过它,我们能够制作一些炫酷的前端音乐界面。

下面,我将分析一个来自云音乐技术团队的音频可视化开发案例,快速帮助小白,制作自己喜欢的炫酷的音频可视化界面。

先上图

想开发这么一个炫酷的音频界面,我们可以先来聊聊 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>=0dis每次减一,总共550次,再设置条件为每50次执行一次绘制操作,在每次绘制之前,通过clearRect(x,y,width,height)方法将画布上给定矩形清空,它的4个参数分别表示要清除的矩形左上角的x,y坐标,以及要清空矩形的宽度和高度,单位以像素计算。然后再通过fillText()画布指定位置绘制倒计时数字,该方法接收四个参数:text输出的文本,x绘制文本的x坐标,y绘制文本的y坐标,注意:这两个值都是相对于画布,最后一个参数maxWidth表示允许文本的最大宽度,它是一个可选参数。

接着我们通过递归的方式调用animation()函数直到倒计时结束,最后在外部调用一下animation()函数,至此,一个简单的倒计时界面完成。我们还可以给canvas通过innerWidthinnerHeight设置

画布大小。

canvas可以绘制各种图形,更多内容请自行参看canvas内容

聊完了canvas,接下来就是我们的正题了。

Web Audio

在开始之前,我们还需要了解什么是Web Audio。

Web Audio 是 Web 端处理和分析音频的一套 API 。它可以使用户在音频上下文中进行音频操作,具有模块化路由的特点,它也使我们能够控制音频的空间化。

通过Web Audio,我们能够实现取数据映射数据两个过程,下面我们将实现这两个过程。

项目实现

我们先在页面创建一个canvas元素和一个audio标签以及一个用于作播放按钮的a标签。

然后在JavaScript里面获取audioa这两个元素,并给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.webkitAudioContext)();

通过 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 获取音频的频率数据。

然而 canvasWeb Audio的用处远远不止于此,读者还可以发挥想象力和创造力,开发出更多有意思的项目。

附上项目源码:github.com/anpeier/les…