Reputation: 3
In the below code i need to show the wave form when the user speaks, but i'm not sure about the code, it does't gets me positive
Reference image Expected Output
Also it needs to be varies based on the amplitude change and color of the wave also to be changed based on the resultant amplitude
///
class Waveform extends StatelessWidget {
final List<double> amplitudes;
const Waveform(this.amplitudes, {super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100.0,
child: CustomPaint(
painter: WaveformPainter(amplitudes),
),
);
}
}
///
class WaveformPainter extends CustomPainter {
final List<double> amplitudes;
WaveformPainter(this.amplitudes);
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = Colors.blue
..strokeCap = StrokeCap.round
..strokeWidth = 4.0;
final Path path = Path();
for (int i = 0; i < amplitudes.length; i++) {
final double x = i * size.width / (amplitudes.length - 1);
final double y = (1 - amplitudes[i]) * size.height / 2;
if (i == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
// Adding gradient
paint.shader = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.blue.withOpacity(0.5),
Colors.blue.withOpacity(0.0),
],
).createShader(Rect.fromPoints(Offset(0, 0), Offset(0, size.height)));
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Upvotes: 0
Views: 297
Reputation: 2458
Your approach looks good but I assume it results in sharp lines instead of smooth curves at peaks. One way to achieve the smooth wave is by using the CatmullRomSpline. For this, you will need at least 4 values in your input list of amplitues. If you don't have 4 points you will have to generate them.
@override
void paint(Canvas canvas, Size size) {
// normalize amplitude values based on the size
final points = normalize(amplitudes, size);
// ensure that at least 4 points are available;
final spline = CatmullRomSpline(points);
final samples = spline.generateSamples().toList();
final path = Path();
final startOffset = samples.first.value;
path.moveTo(startOffset.dx, startOffset.dy);
for (final sample in samples) {
path.lineTo(sample.value.dx, sample.value.dy);
}
final paint = /* config your paint */;
canvas.drawPath(path, paint);
}
Upvotes: 0