返回
弹指一挥间,Flutter自组蛛网图绘制+动画实践
Android
2023-11-27 16:22:44
1. 静态蛛网图
1.1 创建AbilityWidget组件
在 Flutter 中,自定义组件是构建复杂界面的基石。为了创建蛛网图,我们需要一个名为AbilityWidget的自定义组件。这个组件将负责绘制蛛网图的各个元素,如外圈、内圈和文字。
class AbilityWidget extends StatelessWidget {
final double value;
final String name;
const AbilityWidget({Key key, @required this.value, @required this.name}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: AbilityPainter(value: value, name: name),
);
}
}
1.2 绘制外圈
外圈是蛛网图的核心元素,它代表了整体数据范围。在AbilityPainter类中,我们使用drawCircle
方法绘制外圈。
class AbilityPainter extends CustomPainter {
final double value;
final String name;
AbilityPainter({@required this.value, @required this.name});
@override
void paint(Canvas canvas, Size size) {
// 绘制外圈
final outerCirclePaint = Paint()
..color = Colors.grey[200]
..strokeWidth = 2.0;
canvas.drawCircle(size.center(Offset.zero), size.width / 2, outerCirclePaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
1.3 绘制内圈
内圈是蛛网图的第二层元素,它代表了数据的分段范围。在AbilityPainter类中,我们使用drawArc
方法绘制内圈。
class AbilityPainter extends CustomPainter {
final double value;
final String name;
AbilityPainter({@required this.value, @required this.name});
@override
void paint(Canvas canvas, Size size) {
// 绘制内圈
final innerCirclePaint = Paint()
..color = Colors.blue[400]
..strokeWidth = 2.0;
final rect = Rect.fromCircle(center: size.center(Offset.zero), radius: size.width / 2);
canvas.drawArc(rect, -pi / 2, value * pi, false, innerCirclePaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
1.3 绘制文字
文字是蛛网图的重要组成部分,它标识了每个数据段的名称和值。在AbilityPainter类中,我们使用drawText
方法绘制文字。
class AbilityPainter extends CustomPainter {
final double value;
final String name;
AbilityPainter({@required this.value, @required this.name});
@override
void paint(Canvas canvas, Size size) {
// 绘制文字
final textStyle = TextStyle(fontSize: 12.0, color: Colors.black);
final textPainter = TextPainter(
text: TextSpan(text: '$name: ${(value * 100).toStringAsFixed(1)}%', style: textStyle),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(canvas, size.center(Offset.zero) + Offset(0.0, -size.height / 4));
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
1.4 绘制范围
范围是蛛网图的外围元素,它指示了数据段的最高值和最低值。在AbilityPainter类中,我们使用drawRange
方法绘制范围。
class AbilityPainter extends CustomPainter {
final double value;
final String name;
AbilityPainter({@required this.value, @required this.name});
@override
void paint(Canvas canvas, Size size) {
// 绘制范围
final rangePaint = Paint()
..color = Colors.grey[200]
..strokeWidth = 1.0;
canvas.drawLine(Offset(size.width / 2, 0.0), Offset(size.width / 2, size.height), rangePaint);
canvas.drawLine(0.0, size.height / 2, size.width, size.height / 2, rangePaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
2. 动画效果
为了让蛛网图更加生动,我们添加了动画效果。在AbilityWidget类中,我们使用TweenAnimationBuilder
来实现动画效果。
class AbilityWidget extends StatefulWidget {
final double value;
final String name;
const AbilityWidget({Key key, @required this.value, @required this.name}) : super(key: key);
@override
_AbilityWidgetState createState() => _AbilityWidgetState();
}
class _AbilityWidgetState extends State<AbilityWidget> with SingleTickerProviderStateMixin {
Animation<double> _animation;
@override
void initState() {
super.initState();
_animation = Tween(begin: 0.0, end: widget.value).animate(CurvedAnimation(parent: _controller, curve: Curves.easeIn));
_controller.forward();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: AbilityPainter(value: _animation.value, name: widget.name),
);
}
final AnimationController _controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
3. 组件封装
现在,我们已经创建了AbilityWidget组件,并添加了动画效果。我们可以将这个组件封装成一个单独的Dart包,这样其他开发者就可以轻松地将其集成到他们的项目中。
结语
在这个教程中,我们学习了如何使用Flutter构建一个动态的蛛网图组件,包括绘制外圈、内圈、文字和范围,以及添加动画效果。希望这个教程对你有帮助,也欢迎你提出问题或建议。