js实现信号波图
使用 Canvas 绘制信号波图
通过 HTML5 的 Canvas API 可以动态绘制信号波形。以下是一个基本实现示例:
const canvas = document.getElementById('waveCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
function drawSineWave() {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
const amplitude = 50; // 振幅
const frequency = 0.02; // 频率
const offsetY = height / 2; // Y轴偏移
for (let x = 0; x < width; x++) {
const y = offsetY + amplitude * Math.sin(x * frequency);
ctx.lineTo(x, y);
}
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.stroke();
}
// 添加动画效果
let phase = 0;
function animate() {
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
const amplitude = 50;
const frequency = 0.02;
for (let x = 0; x < width; x++) {
const y = height/2 + amplitude * Math.sin(x * frequency + phase);
ctx.lineTo(x, y);
}
ctx.strokeStyle = 'red';
ctx.stroke();
phase += 0.05;
requestAnimationFrame(animate);
}
// 选择静态绘制或动画
// drawSineWave();
animate();
使用 SVG 实现波形图
SVG 更适合需要缩放和交互的场景:
const svg = document.getElementById('waveSvg');
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
svg.appendChild(path);
function updateWave() {
let d = '';
const amplitude = 30;
const points = 100;
for (let i = 0; i <= points; i++) {
const x = (i / points) * 300;
const y = 50 + amplitude * Math.sin(i * 0.2);
d += (i === 0 ? 'M' : 'L') + x + ',' + y;
}
path.setAttribute('d', d);
path.setAttribute('stroke', 'green');
path.setAttribute('fill', 'none');
path.setAttribute('stroke-width', '2');
}
updateWave();
使用第三方库(Chart.js)
对于更复杂的波形可视化,可以使用专业图表库:
import Chart from 'chart.js/auto';
const ctx = document.getElementById('waveChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: Array.from({length: 100}, (_, i) => i),
datasets: [{
label: 'Signal Wave',
data: Array.from({length: 100}, (_, i) => Math.sin(i * 0.2) * 50),
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
}
}
});
实时音频波形可视化
如果需要处理真实音频信号,可以使用 Web Audio API:
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const analyser = audioContext.createAnalyser();
analyser.fftSize = 256;
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
const source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
visualize();
});
function visualize() {
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
function draw() {
analyser.getByteTimeDomainData(dataArray);
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
const sliceWidth = width / bufferLength;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const v = dataArray[i] / 128.0;
const y = v * height / 2;
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
x += sliceWidth;
}
ctx.stroke();
requestAnimationFrame(draw);
}
draw();
}
性能优化建议
对于高频更新的波形图,考虑以下优化措施:
- 使用 requestAnimationFrame 进行动画循环
- 对于静态波形,使用离屏 Canvas 预渲染
- 减少不必要的 DOM 操作
- 对于大数据集,考虑降采样显示
以上方法可根据具体需求组合使用,Canvas 适合高性能绘图,SVG 适合矢量图形,而专业图表库能快速实现复杂可视化需求。







