Is it possible to somehow do in flutter what is shown in the GIF?
And so that the starting point always displays a number (in what position this point is at the moment), in the range from 0-100.
CodePudding user response:
some packages that can provide this in a better and neat way
https://pub.dev/packages/syncfusion_flutter_charts https://pub.dev/packages/charts_flutter
CodePudding user response:
Try this (if you need explanation, comment below)
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin{
late final AnimationController _controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 3)
);
late final Size size = const Size(400,400);
late Path path = Path()
..moveTo(0, size.height -100)
..cubicTo(
size.width/2-50, 0,
size.width/2 50, size.height,
size.width, 0
);
late PathAnimation pathAnimation = PathAnimation(path: path);
@override
void initState() {
super.initState();
_controller.forward();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
),
body: Center(
child: ClipRect(
child: AnimatedBuilder(
animation: _controller,
child: Container(
height: 400,
width: 400,
decoration: BoxDecoration(
color: Colors.blue[100],
border: Border.all(
color: Colors.black,
width: 3,
)
),
),
builder: (context, child) {
return CustomPaint(
foregroundPainter: PathPainter(
animation: _controller.value,
pathAnimation: pathAnimation,
),
child: child
);
}
),
),
),
),
);
}
}
class PathAnimation {
final Path path;
Path currentPath = Path();
late final List<PathMetric> pathSegments;
late final double totalLength;
double currentLength = 0;
int currentPathIndex = 0;
PathAnimation({
required this.path
}) {
pathSegments = path.computeMetrics().toList();
totalLength = pathSegments.fold(0, (value, element) => value element.length);
}
Path getCurrentPath(double animation) {
while (animation > (currentLength pathSegments[currentPathIndex].length) / totalLength) {
double segmentLength = pathSegments[currentPathIndex].length;
currentPath.addPath(
pathSegments[currentPathIndex].extractPath(0, segmentLength),
Offset.zero
);
currentPathIndex ;
currentLength = segmentLength;
}
if (currentPathIndex >= pathSegments.length) return currentPath;
double missingPartLength = animation - currentLength / totalLength;
double newSegmentLength = pathSegments[currentPathIndex].length;
return
currentPath..addPath(
pathSegments[currentPathIndex].extractPath(0, missingPartLength * newSegmentLength),
Offset.zero
);
}
}
class PathPainter extends CustomPainter{
double animation;
PathAnimation pathAnimation;
PathPainter({
required this.animation,
required this.pathAnimation,
});
@override
void paint(Canvas canvas, Size size) {
canvas.drawPath(
pathAnimation.getCurrentPath(animation),
Paint()
..style = PaintingStyle.stroke
..strokeWidth = 3
..color = Colors.red
);
}
@override
bool shouldRepaint(PathPainter oldDelegate) {
return animation != oldDelegate.animation;
}
}