音乐波形图动画效果是Loading动画系列中的一个,github地址:https://github.com/LaoMengFlutter/flutter-do
Loading动画效果如下
其中音乐波形图动画效果如下
下面我们看看音乐波形图动画效果是如何实现的?动画效果实现的思路是绘制一个静止的效果,其中可变的效果使用参数控制,效果如下:
一个柱形条代码如下:
代码语言:javascript复制class Bar extends StatelessWidget {
final double width;
final double height;
final Color color;
final BorderRadiusGeometry borderRadius;
const Bar({
Key? key,
required this.width,
required this.height,
this.color = Colors.white,
required this.borderRadius,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: width,
height: height,
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: color,
borderRadius: borderRadius,
),
));
}
}
4个柱形条代码如下:
代码语言:javascript复制Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: .5 * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: .5 * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: .5 * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: .5 * widget.height,
),
],
)
下面让4个柱形条动起来,改变其高度,代码如下:
代码语言:javascript复制class BarMusicLoading extends StatefulWidget {
final double width;
final double height;
final Color color;
final BorderRadiusGeometry borderRadius;
final Duration duration;
final Curve curve;
const BarMusicLoading(
{Key? key,
this.width = 3.0,
this.height = 40.0,
this.color = Colors.blue,
this.borderRadius = const BorderRadius.only(
topLeft: Radius.circular(3), topRight: Radius.circular(3)),
this.duration = const Duration(milliseconds: 3000),
this.curve = Curves.easeInOut})
: super(key: key);
@override
_BarMusicLoadingState createState() => _BarMusicLoadingState();
}
class _BarMusicLoadingState extends State<BarMusicLoading>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _animation, _animation1, _animation2, _animation3;
List values = [
[0.0, 0.7, 0.4, 0.05, 0.95, 0.3, 0.9, 0.4, 0.15, 0.18, 0.75, 0.01],
[0.05, 0.95, 0.3, 0.9, 0.4, 0.15, 0.18, 0.75, 0.01, 0.0, 0.7, 0.4],
[0.9, 0.4, 0.15, 0.18, 0.75, 0.01, 0.0, 0.7, 0.4, 0.05, 0.95, 0.3],
[0.18, 0.75, 0.01, 0.0, 0.7, 0.4, 0.05, 0.95, 0.3, 0.9, 0.4, 0.15],
];
@override
void initState() {
_controller = AnimationController(vsync: this, duration: widget.duration)
..repeat();
_animation = TweenSequence([
...List.generate(11, (index) {
return TweenSequenceItem(
tween: Tween(begin: values[0][index], end: values[0][index 1]),
weight: 100.0 / values.length);
}).toList()
]).animate(CurvedAnimation(parent: _controller, curve: widget.curve));
_animation1 = TweenSequence([
...List.generate(11, (index) {
return TweenSequenceItem(
tween: Tween(begin: values[1][index], end: values[1][index 1]),
weight: 100.0 / values.length);
}).toList()
]).animate(CurvedAnimation(parent: _controller, curve: widget.curve));
_animation2 = TweenSequence([
...List.generate(11, (index) {
return TweenSequenceItem(
tween: Tween(begin: values[2][index], end: values[2][index 1]),
weight: 100.0 / values.length);
}).toList()
]).animate(CurvedAnimation(parent: _controller, curve: widget.curve));
_animation3 = TweenSequence([
...List.generate(11, (index) {
return TweenSequenceItem(
tween: Tween(begin: values[3][index], end: values[3][index 1]),
weight: 100.0 / values.length);
}).toList()
]).animate(CurvedAnimation(parent: _controller, curve: widget.curve));
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: _animation.value * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: _animation1.value * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: _animation2.value * widget.height,
),
Bar(
color: widget.color,
width: widget.width,
borderRadius: widget.borderRadius,
height: _animation3.value * widget.height,
),
],
);
});
}
}
最终的效果如下: