一、效果展示
HTML5+JS實現一個簡單的音頻可視化
二、代碼
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>音頻可視化</title><style></style></head><body><divstyle="display: flex;justify-content: center;align-items: center;flex-direction: column;"><divclass="musicBox"style="position: relative; width: 500px; height: 500px"><canvasid="audioCanvas"width="500"height="500"style="position: absolute; left: 0; top: 0"></canvas><svgt="1716202136861"class="icon"viewBox="0 0 1024 1024"version="1.1"xmlns="http://www.w3.org/2000/svg"p-id="4458"width="68"height="68"style="position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);"><pathd="M701.6 196.53m-15 0a15 15 0 1 0 30 0 15 15 0 1 0-30 0Z"fill="#E159D3"p-id="4459"></path><pathd="M956.29 310.21a482.39 482.39 0 1 0-847.9 452v120.36c0 71.4 58.42 130.76 129.82 130.1a127.79 127.79 0 0 0 100.44-49.85 120.4 120.4 0 0 0 21-103.43c-5.58-21.49-11.71-59-11.71-71.71S354 737.47 359.62 716a120.4 120.4 0 0 0-21-103.43 128.55 128.55 0 0 0-209.75 9.13c-20.91-64.82-25.25-135-11.25-205.6 28.7-144.71 172.14-286.19 317.16-313.27C690.37 55.1 914.24 250.88 914.24 498a402.4 402.4 0 0 1-19.36 123.71 128.55 128.55 0 0 0-209.74-9.13 120.4 120.4 0 0 0-21 103.43c5.58 21.49 11.71 59 11.71 71.71s-6.13 50.22-11.71 71.71a120.4 120.4 0 0 0 21 103.43 127.8 127.8 0 0 0 101.67 49.85 128.59 128.59 0 0 0 128.58-128.62V762.25a483 483 0 0 0 40.9-452z m-767.9 381.87c0-26.24 20.49-48.33 46.71-49.34a48.41 48.41 0 0 1 40.41 18.85 39.94 39.94 0 0 1 6.78 34.34c-5.84 22.48-14.29 68.12-14.29 91.85s8.45 69.37 14.29 91.85a39.94 39.94 0 0 1-6.78 34.37A48.38 48.38 0 0 1 237 932.86a48.64 48.64 0 0 1-48.64-48.64z m647 191.4c0 26.24-20.49 48.33-46.71 49.34a48.41 48.41 0 0 1-40.4-18.82 39.94 39.94 0 0 1-6.78-34.34c5.84-22.48 14.29-68.12 14.29-91.85s-8.45-69.37-14.29-91.85a39.94 39.94 0 0 1 6.78-34.34 48.41 48.41 0 0 1 40.41-18.85c26.22 1 46.71 23.1 46.71 49.34z"fill="#E159D3"p-id="4460"></path><pathd="M651.51 154.09a371.39 371.39 0 0 0-419.35 100.28 373.69 373.69 0 0 0-30.07 39.56 15 15 0 1 0 25 16.52A341.48 341.48 0 0 1 512 157a339.17 339.17 0 0 1 128.23 24.93 15 15 0 1 0 11.29-27.79z"fill="#E159D3"p-id="4461"></path><pathd="M456.91 668.17c-20.66 1.25-37.52 19.95-37.52 40.65v157.92c0 20.7 16.85 39.4 37.52 40.65a40 40 0 0 0 42.48-39.93V708.1a40 40 0 0 0-42.48-39.93zM563.91 698.12c-20.66 1.25-37.52 19.95-37.52 40.65v98c0 20.7 16.85 39.4 37.52 40.65a40 40 0 0 0 42.48-39.93V738a40 40 0 0 0-42.48-39.88z"fill="#48BCFF"p-id="4462"></path></svg></div><audio id="audio" src="./audio/游戲城大冒險.mp3" controls></audio></div></body><script>//需要可視化的數據let audioArr;//我們需要一個音樂播放器和一個canvas進行顯示const audioElement = document.getElementById("audio");const canvas = document.getElementById("audioCanvas");//canvas的一些基本設置const ctx = canvas.getContext("2d");const centerX = canvas.width / 2;const centerY = canvas.height / 2;const radius = 50; // 圓的半徑//初始化let isInit = false;let analyser = null;// 當音樂播放audioElement.onplay = () => {if (!isInit) {isInit = true;}const audioContext = new AudioContext(); // 創建音頻上下文const audioSrc = audioContext.createMediaElementSource(audioElement); // 創建音頻源analyser = audioContext.createAnalyser(); // 創建分析器analyser.fftSize = 128; // 設置傅里葉變換的大小,影響線條密度audioArr = new Uint8Array(analyser.frequencyBinCount); // 創建一個無符號字節數組存儲頻率數據,該API參考ES6文檔audioSrc.connect(analyser); // 連接音頻源和分析器analyser.connect(audioContext.destination); // 連接分析器和音頻目的地//動畫開始animate();};// 繪制圓形const drawGradientCircle = () => {ctx.beginPath();// 創建一個從中心點向外的徑向漸變const grd = ctx.createLinearGradient(centerX - radius,centerY - radius,centerX + radius,centerY + radius);grd.addColorStop("0", "purple");grd.addColorStop("0.3", "magenta");grd.addColorStop("0.5", "blue");grd.addColorStop("0.6", "green");grd.addColorStop("0.8", "yellow");grd.addColorStop(1, "red");ctx.strokeStyle = grd;ctx.arc(centerX, centerY, radius - 2, 0, Math.PI * 2); // 繪制一個完整的圓ctx.stroke(); // 畫圓復制代碼};//繪制線條const drawLinesFromCircle = () => {ctx.lineWidth = 2;//使用音頻的頻率數據繪制線條//為了美觀,我們繪制兩條線,一條是頻率數據,另一條是對稱的//也可以去使用其它的方式繪制線條audioArr.forEach((value, index) => {const baseAngle = (index / audioArr.length) * Math.PI * 2; // 基礎角度const angle1 = baseAngle; // 第一條線的角度const angle2 = baseAngle + Math.PI; // 對稱線的角度,相差π(180度)// 繪制第一條線{const endX1 = centerX + radius * Math.cos(angle1);const endY1 = centerY + radius * Math.sin(angle1);const startX1 = centerX + (radius + value * 0.4) * Math.cos(angle1); // 使用value控制長度const startY1 = centerY + (radius + value * 0.4) * Math.sin(angle1);ctx.beginPath();ctx.moveTo(startX1, startY1);ctx.lineTo(endX1, endY1);ctx.strokeStyle = `hsl(${index * 3.6}, 100%, 50%)`;ctx.stroke();}// 繪制對稱的第二條線{const endX2 = centerX + radius * Math.cos(angle2);const endY2 = centerY + radius * Math.sin(angle2);const startX2 = centerX + (radius + value * 0.4) * Math.cos(angle2);const startY2 = centerY + (radius + value * 0.4) * Math.sin(angle2);ctx.beginPath();ctx.moveTo(startX2, startY2);ctx.lineTo(endX2, endY2);ctx.strokeStyle = `hsl(${(index + audioArr.length / 2) * 3.6}, 100%, 50%)`; // 調整顏色以保持對稱性且有所區別ctx.stroke();}});};//播放動畫const animate = () => {ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除畫布if (!isInit) return;analyser.getByteFrequencyData(audioArr); // 獲取頻率數據drawGradientCircle(); // 繪制圓形drawLinesFromCircle(); // 繪制伸展的線條requestAnimationFrame(animate); // 重復繪制以創建動畫效果};</script>
</html>
三、VUE3+TS版本
前端:音頻可視化(VUE3+TS版本)-CSDN博客