[英]How to animate line draw in custom painter in Flutter?
I want to animate the line drawing in custom painter canvas.我想在自定义画家画布中为线条绘制动画。 So far what I can do is create two circles at two points and then create a line between those two points.
到目前为止,我能做的是在两点创建两个圆,然后在这两点之间创建一条线。 But I don't know how to animate the line as if it is going from one point to the other.
但我不知道如何为这条线设置动画,就好像它从一个点到另一个点一样。 I have tried something but I can't make it work.
我已经尝试了一些东西,但我无法让它工作。 Please check the code and suggest me if you have any idea.
如果您有任何想法,请检查代码并建议我。
import 'package:flutter/material.dart';
import 'dart:math' as math;
class ProgressMonitorAnimation extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ProgressMonitorAnimationState();
}
class _ProgressMonitorAnimationState extends State<ProgressMonitorAnimation> with TickerProviderStateMixin {
double _progress = 0.0;
Animation<double> animation;
@override
void initState() {
var controller = AnimationController(duration: Duration(milliseconds: 3000), vsync: this);
animation = Tween(begin: 1.0, end: 0.0).animate(controller)..addListener(() {
setState(() {
_progress = animation.value;
});
});
controller.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return Transform(
alignment: Alignment.center,
transform: Matrix4.rotationX(math.pi),
child: CustomPaint(
foregroundPainter: ProgressPainter(_progress),
),
);
}
}
class ProgressPainter extends CustomPainter {
double _progress;
ProgressPainter(this._progress);
@override
void paint(Canvas canvas, Size size) {
final Paint circlePainter = Paint()..color = Colors.green;
final Paint linePainter = Paint()..color = Colors.black..strokeWidth = 4..strokeCap = StrokeCap.round;
canvas.drawCircle(Offset(0.0, 30.0 * 3), 10.0, circlePainter);
canvas.drawCircle(Offset(15.0 * 2, 80.0 * 3), 10.0, circlePainter);
canvas.drawLine(Offset(0.0 / (_progress * 10), 30.0 * 3), Offset((30.0 * 3) + (15.0) / (_progress * 15) * 2, (80.0 * 3) / (_progress * 15)), linePainter);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
You can do as follows using flutter Custom Painter.您可以使用 flutter Custom Painter 执行以下操作。
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class AnimatedPathPainter extends CustomPainter {
final Animation<double> _animation;
AnimatedPathPainter(this._animation) : super(repaint: _animation);
Path _createAnyPath(Size size) {
return Path()
// ..moveTo(size.height / 4, size.height / 4)
// ..lineTo(size.height, size.width / 2)
// ..lineTo(size.height / 2, size.width)
..quadraticBezierTo(size.height / 2, 100, size.width, size.height);
}
@override
void paint(Canvas canvas, Size size) {
final animationPercent = this._animation.value;
print("Painting + ${animationPercent} - ${size}");
final path = createAnimatedPath(_createAnyPath(size), animationPercent);
final Paint paint = Paint();
paint.color = Colors.black;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 4.0;
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Path createAnimatedPath(
Path originalPath,
double animationPercent,
) {
// ComputeMetrics can only be iterated once!
final totalLength = originalPath
.computeMetrics()
.fold(0.0, (double prev, PathMetric metric) => prev + metric.length);
final currentLength = totalLength * animationPercent;
return extractPathUntilLength(originalPath, currentLength);
}
Path extractPathUntilLength(
Path originalPath,
double length,
) {
var currentLength = 0.0;
final path = new Path();
var metricsIterator = originalPath.computeMetrics().iterator;
while (metricsIterator.moveNext()) {
var metric = metricsIterator.current;
var nextLength = currentLength + metric.length;
final isLastSegment = nextLength > length;
if (isLastSegment) {
final remainingLength = length - currentLength;
final pathSegment = metric.extractPath(0.0, remainingLength);
path.addPath(pathSegment, Offset.zero);
break;
} else {
// There might be a more efficient way of extracting an entire path
final pathSegment = metric.extractPath(0.0, metric.length);
path.addPath(pathSegment, Offset.zero);
}
currentLength = nextLength;
}
return path;
}
class AnimatedPathDemo extends StatefulWidget {
@override
_AnimatedPathDemoState createState() => _AnimatedPathDemoState();
}
class _AnimatedPathDemoState extends State<AnimatedPathDemo>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Completer<GoogleMapController> _controllerMap = Completer();
static final CameraPosition _initialPosition = CameraPosition(
// target: LatLng(12.947437, 77.685345),
target: LatLng(7.8731, 80.7718),
zoom: 8,
);
void _startAnimation() {
_controller.stop();
_controller.reset();
_controller.repeat(
period: Duration(seconds: 2),
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: const Text('Animated Paint')),
body: Stack(
children: <Widget>[
GoogleMap(
// rotateGesturesEnabled: false,
mapType: MapType.normal,
compassEnabled: false,
initialCameraPosition: _initialPosition,
// polylines: _polylines,
// markers: _markers,
onMapCreated: (GoogleMapController controller) {
// controller.setMapStyle(Utils.mapStyles);
_controllerMap.complete(controller);
},
),
SizedBox(
height: 300,
width: 300,
child: new CustomPaint(
painter: new AnimatedPathPainter(_controller),
),
),
],
),
floatingActionButton: new FloatingActionButton(
onPressed: _startAnimation,
child: new Icon(Icons.play_arrow),
),
);
}
@override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.