仅仅通过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 <audio> 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>