Flutter 中的路径动画:实现沿路径运动

Flutter 中的路径动画:实现沿路径运动

5 回复

使用 PathAnimationController 结合 CustomPainter 实现。

更多关于Flutter 中的路径动画:实现沿路径运动的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中,使用 PathMotionPathDrawer 可以实现沿路径运动的动画。通过 Path 定义路径,结合 AnimationControllerAnimatedBuilder 控制动画进度。

在 Flutter 中实现沿路径运动的动画,可以使用 PathPathMetrics 来定义路径,并通过 CustomPainterAnimationController 控制动画。以下是简单示例:

  1. 定义路径:使用 Path 类绘制路径。
  2. 测量路径:使用 PathMetrics 获取路径长度和分段信息。
  3. 动画控制:使用 AnimationController 控制动画进度。
  4. 绘制动画:在 CustomPainter 中根据动画进度绘制对象沿路径运动。

示例代码:

class PathAnimation extends StatefulWidget {
  @override
  _PathAnimationState createState() => _PathAnimationState();
}

class _PathAnimationState extends State<PathAnimation> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Path _path;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 3))..repeat();
    _path = Path()
      ..moveTo(50, 50)
      ..quadraticBezierTo(100, 150, 200, 50)
      ..quadraticBezierTo(300, 150, 400, 50);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedBuilder(
          animation: _controller,
          builder: (context, child) {
            return CustomPaint(
              size: Size(400, 200),
              painter: PathPainter(_path, _controller.value),
            );
          },
        ),
      ),
    );
  }
}

class PathPainter extends CustomPainter {
  final Path path;
  final double progress;

  PathPainter(this.path, this.progress);

  @override
  void paint(Canvas canvas, Size size) {
    var pathMetrics = path.computeMetrics();
    var tangent = pathMetrics.elementAt(0).getTangentForOffset(pathMetrics.elementAt(0).length * progress);
    canvas.drawCircle(tangent.position, 10, Paint()..color = Colors.blue);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

这段代码实现了对象沿路径运动的动画效果。

使用CustomPainterPath类结合动画控制器实现。

在 Flutter 中,可以通过 PathPathMetrics 来实现沿路径运动的动画。以下是一个简单的示例,展示如何让一个 widget 沿着自定义路径移动。

1. 创建路径

首先,定义一个 Path 对象,描述你想要 widget 移动的路径。

Path path = Path();
path.moveTo(50, 50); // 起点
path.quadraticBezierTo(150, 50, 150, 150); // 贝塞尔曲线
path.lineTo(150, 250); // 直线
path.cubicTo(150, 300, 50, 300, 50, 250); // 贝塞尔曲线

2. 使用 PathMetrics 获取路径长度

PathMetrics 可以帮助我们获取路径的长度,以便在动画中使用。

PathMetrics pathMetrics = path.computeMetrics();
double pathLength = pathMetrics.first.length;

3. 创建动画控制器

使用 AnimationController 来控制动画的进度。

AnimationController controller = AnimationController(
  vsync: this, // 需要混入 SingleTickerProviderStateMixin
  duration: Duration(seconds: 5),
);

4. 创建动画

使用 Tween 创建一个从 0 到路径长度的动画。

Animation<double> animation = Tween(begin: 0.0, end: pathLength).animate(controller);

5. 使用 PathMetric 获取当前位置

build 方法中,使用 PathMetric 来获取动画当前的位置。

@override
Widget build(BuildContext context) {
  return AnimatedBuilder(
    animation: animation,
    builder: (context, child) {
      PathMetrics pathMetrics = path.computeMetrics();
      Tangent? tangent = pathMetrics.first.getTangentForOffset(animation.value);
      return Transform.translate(
        offset: tangent?.position ?? Offset.zero,
        child: child,
      );
    },
    child: Container(
      width: 50,
      height: 50,
      color: Colors.blue,
    ),
  );
}

6. 启动动画

initState 中启动动画。

@override
void initState() {
  super.initState();
  controller.repeat(); // 循环播放动画
}

7. 清理资源

dispose 中释放动画控制器。

@override
void dispose() {
  controller.dispose();
  super.dispose();
}

完整代码示例

import 'package:flutter/material.dart';

class PathAnimation extends StatefulWidget {
  @override
  _PathAnimationState createState() => _PathAnimationState();
}

class _PathAnimationState extends State<PathAnimation> with SingleTickerProviderStateMixin {
  late AnimationController controller;
  late Animation<double> animation;

  Path path = Path()
    ..moveTo(50, 50)
    ..quadraticBezierTo(150, 50, 150, 150)
    ..lineTo(150, 250)
    ..cubicTo(150, 300, 50, 300, 50, 250);

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    )..repeat();

    PathMetrics pathMetrics = path.computeMetrics();
    double pathLength = pathMetrics.first.length;

    animation = Tween(begin: 0.0, end: pathLength).animate(controller);
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        PathMetrics pathMetrics = path.computeMetrics();
        Tangent? tangent = pathMetrics.first.getTangentForOffset(animation.value);
        return Transform.translate(
          offset: tangent?.position ?? Offset.zero,
          child: child,
        );
      },
      child: Container(
        width: 50,
        height: 50,
        color: Colors.blue,
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

void main() {
  runApp(MaterialApp(
    home: Scaffold(
      body: Center(
        child: PathAnimation(),
      ),
    ),
  ));
}

这个示例展示了如何让一个蓝色方块沿着自定义路径移动。你可以根据需要调整路径和动画的细节。

回到顶部