webAPI实现可视化音频小练习

仅仅通过html、css、js即可实现此效果,下面附上代码,还有很多不足,请多多理解。

html部分:

<canvas id="canvas" width="1500" height="600"></canvas>
    <audio controls id="audio">
        <source src="./audio.mp3" type="audio/mp3" />
        <p>This demo needs a browser supporting the &lt;audio&gt; element.</p>
    </audio>

    <div id="con-panel">
        <button type="button" id="play" data-playing="false">play</button>
        音量:<input type="range" id="volume" min="0" max="2" value="1" step="0.01">
    </div>

css样式,可以忽略这里:

*{
            margin: 0;
            padding: 0;
        }
        #con-panel{
            background-color: white;
            position: fixed;
            top: 0;
            right: 0;
            display: flex;
            flex-flow: wrap column;
        }
        body{
            text-align: center;
        }
        audio{
            display: none;
        }

js部分,结合js和canvas实现:

<script>
        var audioContext = new (window.AudioContext || window.webkitAudioContext)();

        const analyser = audioContext.createAnalyser();
        analyser.fftSize = 512;
        const bufferLength = analyser.frequencyBinCount;
        const dataArray = new Uint8Array(bufferLength);

        const audioElement = document.querySelector('audio');
        const track = audioContext.createMediaElementSource(audioElement);
        track.connect(analyser);
       
        const gainNode = audioContext.createGain();
        const volumeControl = document.querySelector('#volume');
        volumeControl.addEventListener('input', function() {
            gainNode.gain.value = this.value;
        }, false);
        track.connect(gainNode).connect(audioContext.destination);

        const WIDTH = 1500;
        const HEIGHT = 600;
        let canvas = document.getElementById("canvas");
        let canvasCtx = canvas.getContext("2d")

        function draw() {
            canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
            drawVisual = requestAnimationFrame(draw);
           
            analyser.getByteFrequencyData(dataArray);
            canvasCtx.fillStyle = 'rgb(50, 50, 50)';
            canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);

            var barWidth = WIDTH / bufferLength;
            var barHeight;
            var x = 0;
           
            for(var i = 0; i < bufferLength; i++) {
                barHeight = dataArray[i];

                let linear = canvasCtx.createLinearGradient(x,HEIGHT-barHeight,barWidth,barHeight);
                linear.addColorStop(0,"rgba(231, 157, 47, 1)");
                linear.addColorStop(1,"rgba(235, 84, 255, 1)");
                canvasCtx.fillStyle = linear;
                canvasCtx.fillRect(x,HEIGHT-barHeight*2,barWidth,barHeight*2);

                x += barWidth + 1;
            }
        };

        const playButton = document.querySelector('#play');
        playButton.addEventListener('click',function(){
            if (audioContext.state === 'suspended') {
                audioContext.resume();
            }
            if (this.dataset.playing === 'false') {
                audioElement.play();
                this.dataset.playing = 'true';
                this.innerText = 'pause';
            } else if (this.dataset.playing === 'true') {
                audioElement.pause();
                cancelAnimationFrame(drawVisual);
                this.dataset.playing = 'false';
                this.innerText = 'play';
            }
        },false)

        audioElement.addEventListener('playing',()=>{
            draw();
        })

        audioElement.addEventListener('pause',()=>{
            cancelAnimationFrame(drawVisual);
        })

        audioElement.addEventListener('ended',()=>{
            playButton.dataset.playing = 'false';
            playButton.innerText = 'play';
            cancelAnimationFrame(drawVisual);
        })

    </script>