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