基于canvas绘制音频可视化

分享一个好玩的,音频可视化。一直以为这玩意的数据需要后端给,没想到前端也可以搞。

记录记录!!!

实现思路

首先创建音频的上下文new AudioContext()。然后创建音频节点和分析器来辅助进行音频数据获取。最后根据API要求将数据传入指定的容器中,然后使用canvas进行绘制即可。这里使用Uint8Array作为容器。具体请参考:AnalyserNode - Web API 接口 |MDN的 (mozilla.org)

具体实现

话不多说,直接上代码。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <title></title>
</head>
<style>
    *{
        margin: 0;
        padding: 0;
    }
    canvas{
        margin: auto;
        background-color: black;
    }
</style>
<body>
    <canvas id="canvas"></canvas>
    <audio src="http://localhost:8081/1.mp3" controls></audio>
    <script>
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var audio = document.querySelector("audio");
        function initCvs(){
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight / 2;
            ctx.fillRect(0,0,canvas.width,canvas.height);
        }
        initCvs()
        
        let isInit = false;
        let array,analyser;
        audio.onplay = function(){
            if(isInit){
                return;
            }
            audio.crossOrigin = "anonymous";
            const audCtx = new AudioContext();  //创建音频上下文
            const source = audCtx.createMediaElementSource(audio);  //创建音频源节点

            analyser = audCtx.createAnalyser();
            analyser.fftSize = 512;    //必须是2的n次幂
            // //创建数组,来接收分析器节点的分析器数据
            array = new Uint8Array(analyser.frequencyBinCount);
            
            source.connect(analyser);
            analyser.connect(audCtx.destination);

            isInit = true;

        }

        function draw(){
            requestAnimationFrame(draw);
            const {width,height} = canvas;
            ctx.clearRect(0,0,width,height);
            if(!isInit) return;
            // 当前频率数据复制到传递到array
            analyser.getByteFrequencyData(array);
            // 将音视频的波形或时域数据复制到array中
            // analyser.getByteTimeDomainData(array);
            let len = array.length / 2;
            const barWidth = width / len / 2;
            // 创建线性渐变
            var grd = ctx.createLinearGradient(0, 0, 0, 200);
            grd.addColorStop(0, "red");
            grd.addColorStop(0.3, "#090");
            grd.addColorStop(0.7, "green");
            grd.addColorStop(1, "blue");
            ctx.fillStyle = grd;
            for(var i=0;i<len;i++){
                const data = array[i];
                const x = i*barWidth;
                const x1 = x + (width / 2);
                const x2 = (width / 2) - x;
                const barHeight = (data / 255) * height;
                const y = height - barHeight;
                ctx.fillRect(x1,y,barWidth-3,barHeight);
                ctx.fillRect(x2,y,barWidth-3,barHeight);
            }
        }
        draw()
    </script>
</body>

</html>
实现效果

 实现样式比较简陋,可以自己根据具体业务来调整。哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值