didvan-app/lib/views/home/media/widgets/audio_waveform_progress.dart

134 lines
4.0 KiB
Dart

import 'package:flutter/material.dart';
import 'dart:math' as math;
class AudioWaveformProgress extends StatelessWidget {
final double progress;
final bool isActive;
final ValueChanged<double>? onChanged;
const AudioWaveformProgress({
super.key,
required this.progress,
this.isActive = true,
this.onChanged,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: onChanged != null
? (details) {
final box = context.findRenderObject() as RenderBox;
final localPosition = details.localPosition;
final value = localPosition.dx / box.size.width;
onChanged?.call(value.clamp(0.0, 1.0));
}
: null,
onHorizontalDragUpdate: onChanged != null
? (details) {
final box = context.findRenderObject() as RenderBox;
final localPosition = details.localPosition;
final value = localPosition.dx / box.size.width;
onChanged?.call(value.clamp(0.0, 1.0));
}
: null,
child: Container(
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: CustomPaint(
painter: WaveformPainter(
progress: progress.clamp(0.0, 1.0),
isActive: isActive,
),
size: Size.infinite,
),
),
);
}
}
class WaveformPainter extends CustomPainter {
final double progress;
final bool isActive;
WaveformPainter({
required this.progress,
required this.isActive,
});
@override
void paint(Canvas canvas, Size size) {
final random = math.Random(42); // استفاده از seed ثابت برای consistency
const barCount = 60; // تعداد میله‌ها
final barWidth = (size.width / barCount) * 0.45; // عرض هر میله
final spacing = size.width / barCount;
final inactivePaint = Paint()
..color = const Color.fromARGB(255, 102, 102, 102)
..strokeWidth = barWidth
..strokeCap = StrokeCap.round;
final activePaint = Paint()
..color = const Color.fromARGB(255, 0, 126, 167)
..strokeWidth = barWidth
..strokeCap = StrokeCap.round;
// رسم میله‌های موج صدا
for (int i = 0; i < barCount; i++) {
final x = i * spacing + spacing / 2;
// ارتفاع تصادفی برای هر میله (شبیه‌سازی موج صدا)
final randomHeight = random.nextDouble();
final minHeight = size.height * 0.2;
final maxHeight = size.height * 0.9;
final barHeight = minHeight + (randomHeight * (maxHeight - minHeight));
final y1 = (size.height - barHeight) / 2;
final y2 = y1 + barHeight;
// تعیین رنگ بر اساس progress
// استفاده از (i + 1) تا میله اول از 1/60 شروع بشه نه 0/60
final barProgress = (i + 1) / barCount;
final paint = barProgress <= progress && isActive ? activePaint : inactivePaint;
canvas.drawLine(
Offset(x, y1),
Offset(x, y2),
paint,
);
}
// // رسم thumb (دایره کوچک) در محل progress
// if (isActive && progress > 0) {
// final thumbX = progress * size.width;
// final thumbPaint = Paint()
// ..color = const Color(0xFF3B82F6)
// ..style = PaintingStyle.fill;
// canvas.drawCircle(
// Offset(thumbX, size.height / 2),
// 6,
// thumbPaint,
// );
// // سایه برای thumb
// final shadowPaint = Paint()
// ..color = const Color(0xFF3B82F6).withOpacity(0.3)
// ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4);
// canvas.drawCircle(
// Offset(thumbX, size.height / 2),
// 8,
// shadowPaint,
// );
// }
}
@override
bool shouldRepaint(WaveformPainter oldDelegate) {
return oldDelegate.progress != progress || oldDelegate.isActive != isActive;
}
}