Advertisement
Pug_coder

Untitled

Dec 27th, 2023
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.25 KB | None | 0 0
  1. import 'package:flutter/material.dart';
  2.  
  3. void main() => runApp(const MyApp());
  4.  
  5. class CatmullRomSpline {
  6. final List<Offset> controlPoints;
  7. final Offset startHandle;
  8. final Offset endHandle;
  9.  
  10. CatmullRomSpline(this.controlPoints, {required this.startHandle, required this.endHandle});
  11.  
  12. Offset transform(double t) {
  13. final double t2 = t * t;
  14. final double t3 = t2 * t;
  15.  
  16. final double h1 = 2 * t3 - 3 * t2 + 1;
  17. final double h2 = -2 * t3 + 3 * t2;
  18. final double h3 = t3 - 2 * t2 + t;
  19. final double h4 = t3 - t2;
  20.  
  21. final double x = h1 * controlPoints[0].dx +
  22. h2 * controlPoints[1].dx +
  23. h3 * startHandle.dx +
  24. h4 * endHandle.dx;
  25.  
  26. final double y = h1 * controlPoints[0].dy +
  27. h2 * controlPoints[1].dy +
  28. h3 * startHandle.dy +
  29. h4 * endHandle.dy;
  30.  
  31. return Offset(x, y);
  32. }
  33. }
  34.  
  35. class TreeNode {
  36. final String label;
  37. final Offset position;
  38. final List<TreeNode> children;
  39.  
  40. TreeNode(this.label, this.position, {this.children = const []});
  41. }
  42.  
  43. final CatmullRomSpline path = CatmullRomSpline(
  44. const <Offset>[
  45. Offset(0.05, 0.75),
  46. Offset(0.18, 0.23),
  47. Offset(0.32, 0.04),
  48. Offset(0.73, 0.5),
  49. Offset(0.42, 0.74),
  50. Offset(0.73, 0.01),
  51. Offset(0.93, 0.93),
  52. Offset(0.05, 0.75),
  53. ],
  54. startHandle: const Offset(0.93, 0.93),
  55. endHandle: const Offset(0.18, 0.23),
  56. );
  57.  
  58. final TreeNode rootNode = TreeNode('A', Offset(0.5, 0.1), children: [
  59. TreeNode('B', Offset(0.2, 0.3), children: [
  60. TreeNode('D', Offset(0.1, 0.5)),
  61. TreeNode('E', Offset(0.3, 0.5)),
  62. ]),
  63. TreeNode('C', Offset(0.8, 0.3), children: [
  64. TreeNode('F', Offset(0.7, 0.5)),
  65. TreeNode('G', Offset(0.9, 0.5)),
  66. ]),
  67. ]);
  68.  
  69. class MyApp extends StatelessWidget {
  70. const MyApp({Key? key}) : super(key: key);
  71.  
  72. static const String _title = 'Flutter Code Sample';
  73.  
  74. @override
  75. Widget build(BuildContext context) {
  76. return const MaterialApp(
  77. title: _title,
  78. home: MyStatelessWidget(),
  79. );
  80. }
  81. }
  82.  
  83. class FollowCurve2D extends StatefulWidget {
  84. const FollowCurve2D({
  85. Key? key,
  86. required this.path,
  87. this.curve = Curves.easeInOut,
  88. required this.child,
  89. this.duration = const Duration(seconds: 1),
  90. }) : super(key: key);
  91.  
  92. final CatmullRomSpline path;
  93. final Curve curve;
  94. final Duration duration;
  95. final Widget child;
  96.  
  97. @override
  98. State<FollowCurve2D> createState() => _FollowCurve2DState();
  99. }
  100.  
  101. class _FollowCurve2DState extends State<FollowCurve2D> with TickerProviderStateMixin {
  102. late AnimationController controller;
  103. late Animation<double> animation;
  104.  
  105. @override
  106. void initState() {
  107. super.initState();
  108. controller = AnimationController(duration: widget.duration, vsync: this);
  109. animation = CurvedAnimation(parent: controller, curve: widget.curve);
  110. controller.repeat();
  111. controller.addListener(() => setState(() {}));
  112. }
  113.  
  114. @override
  115. void dispose() {
  116. controller.dispose();
  117. super.dispose();
  118. }
  119.  
  120. @override
  121. Widget build(BuildContext context) {
  122. final Offset position = widget.path.transform(animation.value) * 2.0 - const Offset(1.0, 1.0);
  123. return Align(
  124. alignment: Alignment(position.dx, position.dy),
  125. child: widget.child,
  126. );
  127. }
  128. }
  129.  
  130. class MyStatelessWidget extends StatelessWidget {
  131. const MyStatelessWidget({Key? key}) : super(key: key);
  132.  
  133. @override
  134. Widget build(BuildContext context) {
  135. return Scaffold(
  136. backgroundColor: Colors.white,
  137. body: Center(
  138. child: FollowCurve2D(
  139. path: path,
  140. duration: const Duration(seconds: 3),
  141. child: buildTree(context, rootNode),
  142. ),
  143. ),
  144. );
  145. }
  146.  
  147. Widget buildTree(BuildContext context, TreeNode node) {
  148. return Stack(
  149. children: [
  150. Positioned(
  151. left: node.position.dx * 400, // Scale the position to fit the screen
  152. top: node.position.dy * 800,
  153. child: CircleAvatar(
  154. backgroundColor: Colors.yellow,
  155. child: DefaultTextStyle(
  156. style: Theme.of(context).textTheme.headline6!,
  157. child: Text(node.label),
  158. ),
  159. ),
  160. ),
  161. for (var child in node.children) buildTree(context, child),
  162. ],
  163. );
  164. }
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement