diff --git a/lib/src/ui/widgets/track/audio_visualizer_widget.dart b/lib/src/ui/widgets/track/audio_visualizer_widget.dart index 64b94c1..e228b6f 100644 --- a/lib/src/ui/widgets/track/audio_visualizer_widget.dart +++ b/lib/src/ui/widgets/track/audio_visualizer_widget.dart @@ -7,8 +7,37 @@ import '../../../context/track_reference_context.dart'; import '../theme.dart'; import 'no_track_widget.dart'; +class AudioVisualizerOptions { + final int count; + final double width; + final double minHeight; + final double maxHeight; + final int durationInMilliseconds; + final Color color; + final double spacing; + final double cornerRadius; + final double barMinOpacity; + + const AudioVisualizerOptions({ + this.count = 7, + this.width = 12, + this.minHeight = 12, + this.maxHeight = 100, + this.durationInMilliseconds = 500, + this.color = Colors.white, + this.spacing = 5, + this.cornerRadius = 9999, + this.barMinOpacity = 0.35, + }); +} + class AudioVisualizerWidget extends StatelessWidget { - const AudioVisualizerWidget({Key? key}) : super(key: key); + final AudioVisualizerOptions options; + + const AudioVisualizerWidget({ + Key? key, + this.options = const AudioVisualizerOptions(), + }) : super(key: key); @override Widget build(BuildContext context) { @@ -31,11 +60,7 @@ class AudioVisualizerWidget extends StatelessWidget { child: Center( child: SoundWaveformWidget( audioTrack: audioTrack, - count: 7, - width: 12, - minHeight: 12, - maxHeight: 100, - durationInMilliseconds: 500, + options: options, ), ), ); @@ -46,21 +71,15 @@ class AudioVisualizerWidget extends StatelessWidget { } class SoundWaveformWidget extends StatefulWidget { - final int count; - final double width; - final double minHeight; - final double maxHeight; - final int durationInMilliseconds; + final AudioVisualizerOptions options; + final AudioTrack? audioTrack; + const SoundWaveformWidget({ super.key, this.audioTrack, - this.count = 7, - this.width = 5, - this.minHeight = 8, - this.maxHeight = 100, - this.durationInMilliseconds = 500, + this.options = const AudioVisualizerOptions(), }); - final AudioTrack? audioTrack; + @override State createState() => _SoundWaveformWidgetState(); } @@ -102,7 +121,7 @@ class _SoundWaveformWidgetState extends State controller = AnimationController( vsync: this, duration: Duration( - milliseconds: widget.durationInMilliseconds, + milliseconds: widget.options.durationInMilliseconds, )) ..repeat(); @@ -118,35 +137,44 @@ class _SoundWaveformWidgetState extends State @override Widget build(BuildContext context) { - final count = widget.count; - final minHeight = widget.minHeight; - final maxHeight = widget.maxHeight; + final count = widget.options.count; + final minHeight = widget.options.minHeight; + final maxHeight = widget.options.maxHeight; return AnimatedBuilder( animation: controller, builder: (c, child) { - //double t = controller.value; - //int current = (samples.length * t).floor(); return Row( mainAxisSize: MainAxisSize.min, children: List.generate( count, - (i) => AnimatedContainer( - duration: Duration( - milliseconds: widget.durationInMilliseconds ~/ count), - margin: i == (samples.length - 1) - ? EdgeInsets.zero - : const EdgeInsets.only(right: 5), - height: samples[i] < minHeight - ? minHeight - : samples[i] > maxHeight - ? maxHeight - : samples[i], - width: widget.width, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(9999), - ), - ), + (i) { + final heightPercent = + ((samples[i] - minHeight) / (maxHeight - minHeight)) + .clamp(0.0, 1.0); + final barOpacity = + (1.0 - widget.options.barMinOpacity) * heightPercent + + widget.options.barMinOpacity; + + return AnimatedContainer( + duration: Duration( + milliseconds: + widget.options.durationInMilliseconds ~/ count), + margin: i == (samples.length - 1) + ? EdgeInsets.zero + : EdgeInsets.only(right: widget.options.spacing), + height: samples[i] < minHeight + ? minHeight + : samples[i] > maxHeight + ? maxHeight + : samples[i], + width: widget.options.width, + decoration: BoxDecoration( + color: widget.options.color.withValues(alpha: barOpacity), + borderRadius: + BorderRadius.circular(widget.options.cornerRadius), + ), + ); + }, ), ); },