|
|
@ -477,10 +477,10 @@ class RealTimeWaveformPainter extends CustomPainter { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 绘制中央时间参考线 |
|
|
/// 绘制中央时间参考线(只保留水平线) |
|
|
void _drawCenterLine( |
|
|
void _drawCenterLine( |
|
|
Canvas canvas, Size size, double centerX, double centerY) { |
|
|
Canvas canvas, Size size, double centerX, double centerY) { |
|
|
// 绘制水平中线 |
|
|
// 只绘制水平中线 |
|
|
final horizontalLinePaint = Paint() |
|
|
final horizontalLinePaint = Paint() |
|
|
..color = |
|
|
..color = |
|
|
(isDarkMode ? Colors.white : Colors.black).withValues(alpha: 0.15) |
|
|
(isDarkMode ? Colors.white : Colors.black).withValues(alpha: 0.15) |
|
|
@ -492,51 +492,25 @@ class RealTimeWaveformPainter extends CustomPainter { |
|
|
horizontalLinePaint, |
|
|
horizontalLinePaint, |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
// 绘制垂直时间参考线(红色,更醒目) |
|
|
// 移除垂直时间参考线和三角形指示器 |
|
|
final centerLinePaint = Paint() |
|
|
|
|
|
..color = Colors.red.withValues(alpha: 0.8) |
|
|
|
|
|
..strokeWidth = 2.0 |
|
|
|
|
|
..style = PaintingStyle.stroke; |
|
|
|
|
|
|
|
|
|
|
|
canvas.drawLine( |
|
|
|
|
|
Offset(centerX, centerY - size.height * 0.4), |
|
|
|
|
|
Offset(centerX, centerY + size.height * 0.4), |
|
|
|
|
|
centerLinePaint, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// 在参考线顶部绘制小三角形指示器 |
|
|
|
|
|
final trianglePath = Path(); |
|
|
|
|
|
final triangleSize = 4.0; |
|
|
|
|
|
trianglePath.moveTo(centerX, centerY - size.height * 0.4); |
|
|
|
|
|
trianglePath.lineTo( |
|
|
|
|
|
centerX - triangleSize, centerY - size.height * 0.4 - triangleSize); |
|
|
|
|
|
trianglePath.lineTo( |
|
|
|
|
|
centerX + triangleSize, centerY - size.height * 0.4 - triangleSize); |
|
|
|
|
|
trianglePath.close(); |
|
|
|
|
|
|
|
|
|
|
|
final trianglePaint = Paint() |
|
|
|
|
|
..color = Colors.red |
|
|
|
|
|
..style = PaintingStyle.fill; |
|
|
|
|
|
|
|
|
|
|
|
canvas.drawPath(trianglePath, trianglePaint); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 绘制实时流动波形 |
|
|
/// 绘制实时流动波形(扩散到整个区域) |
|
|
void _drawWaveform(Canvas canvas, Size size, double centerX, double centerY) { |
|
|
void _drawWaveform(Canvas canvas, Size size, double centerX, double centerY) { |
|
|
final barWidth = 2.5; // 波形条宽度 |
|
|
final barWidth = 2.5; // 波形条宽度 |
|
|
final barSpacing = 0.5; // 波形条间距 |
|
|
final barSpacing = 0.5; // 波形条间距 |
|
|
final totalBarWidth = barWidth + barSpacing; |
|
|
final totalBarWidth = barWidth + barSpacing; |
|
|
|
|
|
|
|
|
// 计算中央参考线左侧可以显示多少个波形条 |
|
|
// 计算整个宽度可以显示多少个波形条 |
|
|
final maxBarsOnLeft = (centerX / totalBarWidth).floor(); |
|
|
final maxBars = (size.width / totalBarWidth).floor(); |
|
|
|
|
|
|
|
|
// 绘制左侧流动波形(历史数据,从右向左流动) |
|
|
// 绘制扩散到整个区域的波形 |
|
|
_drawLeftWaveform( |
|
|
_drawFullWaveform( |
|
|
canvas, centerX, centerY, barWidth, totalBarWidth, maxBarsOnLeft); |
|
|
canvas, size, centerY, barWidth, totalBarWidth, maxBars); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 绘制左侧历史波形(从右向左流动) |
|
|
/// 绘制扩散到整个区域的波形 |
|
|
void _drawLeftWaveform(Canvas canvas, double centerX, double centerY, |
|
|
void _drawFullWaveform(Canvas canvas, Size size, double centerY, |
|
|
double barWidth, double totalBarWidth, int maxBars) { |
|
|
double barWidth, double totalBarWidth, int maxBars) { |
|
|
final dataLength = waveData.length; |
|
|
final dataLength = waveData.length; |
|
|
if (dataLength == 0) return; |
|
|
if (dataLength == 0) return; |
|
|
@ -544,24 +518,25 @@ class RealTimeWaveformPainter extends CustomPainter { |
|
|
// 计算流动偏移量 |
|
|
// 计算流动偏移量 |
|
|
final flowOffset = animationValue * totalBarWidth; |
|
|
final flowOffset = animationValue * totalBarWidth; |
|
|
|
|
|
|
|
|
// 绘制最近的波形条(最多显示maxBars个) |
|
|
// 绘制波形条,从左到右填满整个区域 |
|
|
final displayCount = min(dataLength, maxBars); |
|
|
final displayCount = min(dataLength, maxBars); |
|
|
|
|
|
|
|
|
for (int i = 0; i < displayCount; i++) { |
|
|
for (int i = 0; i < displayCount; i++) { |
|
|
// 计算波形条的x位置:从参考线开始,向左排列,加上流动偏移 |
|
|
// 计算波形条的x位置:从左边开始排列,加上流动偏移 |
|
|
final x = centerX - (i + 1) * totalBarWidth + flowOffset; |
|
|
final x = i * totalBarWidth + flowOffset; |
|
|
|
|
|
|
|
|
|
|
|
// 如果波形条完全移出屏幕右侧,跳过绘制 |
|
|
|
|
|
if (x > size.width) continue; |
|
|
// 如果波形条完全移出屏幕左侧,跳过绘制 |
|
|
// 如果波形条完全移出屏幕左侧,跳过绘制 |
|
|
if (x + barWidth < 0) continue; |
|
|
if (x + barWidth < 0) continue; |
|
|
|
|
|
|
|
|
// 获取对应的音频数据(最新的数据在数组末尾) |
|
|
// 获取对应的音频数据(循环使用数据以填满整个区域) |
|
|
final dataIndex = dataLength - 1 - i; |
|
|
final dataIndex = (dataLength - 1 - (i % dataLength)) % dataLength; |
|
|
if (dataIndex < 0) continue; |
|
|
|
|
|
|
|
|
|
|
|
final amplitude = waveData[dataIndex]; |
|
|
final amplitude = waveData[dataIndex]; |
|
|
|
|
|
|
|
|
// 计算透明度:越远的波形条越透明 |
|
|
// 计算透明度:中央区域更亮,边缘渐暗 |
|
|
final opacity = (1.0 - (i / displayCount) * 0.6).clamp(0.2, 1.0); |
|
|
final distanceFromCenter = (x - size.width / 2).abs() / (size.width / 2); |
|
|
|
|
|
final opacity = (1.0 - distanceFromCenter * 0.4).clamp(0.3, 1.0); |
|
|
|
|
|
|
|
|
_drawWaveBar(canvas, x, centerY, barWidth, amplitude, opacity); |
|
|
_drawWaveBar(canvas, x, centerY, barWidth, amplitude, opacity); |
|
|
} |
|
|
} |
|
|
|