先看效果
planet_widget.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' show Vector3;
import 'package:flutter/gestures.dart';
import 'package:flutter/physics.dart';
class PlanetWidget extends StatefulWidget {
const PlanetWidget({Key? key, required this.children, this.minRadius = 50})
: super(key: key);
@override
_PlanetWidgetState createState() => _PlanetWidgetState();
final List<Widget> children;
final double minRadius;
}
class _PlanetWidgetState extends State<PlanetWidget>
with TickerProviderStateMixin {
late AnimationController animationController;
/// 启动加载或者重新加载的时候用的Controller
late AnimationController reloadAnimationController;
double preAngle = 0.0;
double _radius = -1.0;
List<PlanetTagInfo>? childTagList = [];
/// 当前操作的向量信息
Vector3 currentOperateVector = Vector3(1.0, 0.0, 0.0);
@override
void initState() {
super.initState();
animationController =
AnimationController(lowerBound: 0, upperBound: pi * 2, vsync: this);
reloadAnimationController = AnimationController(
lowerBound: 0,
upperBound: 1,
duration: Duration(milliseconds: 300),
vsync: this);
animationController.addListener(() {
setState(() {
calTagInfo(animationController.value - preAngle);
});
});
reloadAnimationController.addListener(() {
setState(() {});
});
// initData();
}
void initData() {
childTagList = widget.children
.map((e) => PlanetTagInfo(child: e, planetTagPos: Vector3.zero()))
.toList();
currentOperateVector = updateOperateVector(Offset(-1.0, 1.0));
initTagInfo();
WidgetsBinding.instance!.addPostFrameCallback((_) {
reloadAnimationController.forward().then((value) => _reStartAnimation());
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (widget.children.isNotEmpty) {
initData();
}
}
@override
void didUpdateWidget(covariant PlanetWidget oldWidget) {
if (oldWidget.children != this.widget.children) {
if (widget.children.isNotEmpty) {
animationController.reset();
reloadAnimationController.reset();
initData();
}
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
var radius = min(constraints.maxWidth, constraints.maxHeight) / 2.0;
/// 太小就不显示了
if (radius < widget.minRadius) {
return SizedBox.shrink();
}
if (_radius != radius) {
if (_radius == -1.0) {
_radius = radius;
initTagInfo();
} else {
_radius = radius;
resizeTag