第一步创建一个音频上下文(也就是一个管理音频的构造函数)
audioContext = new (window.AudioContext || window.webkitAudioContext)();
第二步通过音频上下文创建出处理音频数据的“人”
analyser = audioContext.createAnalyser();
第三步创建一个读取音频数据的“人”
const source = audioContext.createMediaElementSource(audio.value);
第四步读取音频数据的 “人” 将数据交给处理数据的“人”
source.connect(analyser);
第五步 处理的数据的“人”将处理好的音频数据进行输出外放
analyser.connect(audioContext.destination);
第六步就是Canvas绘图
const drawVisualizer = () => {
if (!visualizer.value || !analyser) return;
const canvas = visualizer.value;
const ctx = canvas.getContext("2d");
// 设置canvas尺寸
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
const draw = () => {
animationId = requestAnimationFrame(draw);
// 获取解析出上下文的数据并存在dataArray中
analyser.getByteFrequencyData(dataArray);
// 初始化清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 设置柱状图参数
const barCount = 160;
const barSpacing = 2;
const barWidth = 2;
const baseHeight = 3;
// 计算总宽度并居中
const totalWidth = (barWidth + barSpacing) * barCount;
const startX = (canvas.width - totalWidth) / 2;
// 绘制音频柱状图
for (let i = 0; i < barCount; i++) {
// 平滑数据
const startIndex = Math.floor((i * dataArray.length) / barCount);
const endIndex = Math.floor(((i + 1) * dataArray.length) / barCount);
let sum = 0;
for (let j = startIndex; j < endIndex; j++) {
sum += dataArray[j];
}
const value = sum / (endIndex - startIndex);
// 计算高度,添加安全检查
const percent = Math.min(Math.max(value / 255, 0), 1); // 确保百分比在 0-1 之间
const height = Math.max(baseHeight, canvas.height * 0.85 * percent);
// 计算位置,添加安全检查
const x = Math.max(0, startX + i * (barWidth + barSpacing));
const y = Math.min(canvas.height - height, canvas.height); // 确保 y 不会小于 0
// 绘制发光效果
ctx.shadowBlur = 12;
ctx.shadowColor = "#00ffea";
try {
// 创建渐变时添加错误处理
if (isFinite(y) && y >= 0 && y <= canvas.height) {
const gradient = ctx.createLinearGradient(x, y, x, canvas.height);
gradient.addColorStop(0, "#00ffea");
gradient.addColorStop(1, "#00ffea33");
ctx.fillStyle = gradient;
} else {
// 如果值无效,使用固定颜色
ctx.fillStyle = "#00ffea";
}
// 绘制主体
ctx.fillRect(x, y, barWidth, height);
// 绘制顶部小圆点
ctx.beginPath();
ctx.arc(x + barWidth / 2, y, barWidth / 2, 0, Math.PI * 2);
ctx.fillStyle = "#00ffea";
ctx.fill();
// 添加星星效果(随机)
if (Math.random() < 0.01) {
ctx.beginPath();
const starX = Math.random() * canvas.width;
const starY = Math.random() * canvas.height;
ctx.arc(starX, starY, 0.8, 0, Math.PI * 2);
ctx.fillStyle = "#00ffea44";
ctx.fill();
}
} catch (error) {
console.error("绘制错误:", error);
continue; // 跳过当前柱子的绘制
}
}
};
draw();
};
标签:canvas,const,音频,height,可视化,barCount,Math
From: https://blog.csdn.net/m0_65227631/article/details/145234167