Flutter绘图动画插件drawing_animation的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter绘图动画插件drawing_animation的使用

简介

drawing_animation 是一个用于在 Flutter 应用中创建绘制动画效果的插件。它支持从静态 SVG 资源或动态创建的 Path 对象中生成动画。

特点

  • 从静态 SVG 资源:支持从简单的 SVG 路径元素中生成动画。
  • 从动态创建的 Path 对象:支持从动态创建的 Path 对象中生成动画,并且可以在动画过程中更改这些对象。
  • 多种动画效果:支持不同的绘制方式(如同时绘制所有路径或逐个绘制路径)和动画曲线(如线性、弹性、反弹等)。

示例效果

From static SVG assets Dynamically created from Path objects
art_egypt1 met_dynamic_1
art_dino2 loader_1
art_order

快速开始

1. 添加依赖

在你的 pubspec.yaml 文件中添加 drawing_animation 依赖:

dependencies:
  drawing_animation: ^1.0.0

2. 添加 SVG 资源

pubspec.yaml 文件中添加你的 SVG 资源文件:

assets:
  - assets/my_drawing.svg

3. 使用 AnimatedDrawing 小部件

3.1 简化版 - 无需动画控制器

默认情况下,每个动画会无限重复。如果你希望动画只运行一次,可以使用回调来设置 runfalse

import 'package:flutter/material.dart';
import 'package:drawing_animation/drawing_animation.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool run = true;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Drawing Animation Example')),
        body: Center(
          child: AnimatedDrawing.svg(
            "assets/my_drawing.svg",
            run: this.run,
            duration: Duration(seconds: 3),
            onFinish: () => setState(() {
              this.run = false;
            }),
          ),
        ),
      ),
    );
  }
}

3.2 标准版 - 使用自定义动画控制器

如果你需要更精细地控制动画或与其他现有动画同步,可以使用自定义的 AnimationController

import 'package:flutter/material.dart';
import 'package:drawing_animation/drawing_animation.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController controller;

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Drawing Animation Example')),
        body: Center(
          child: AnimatedDrawing.svg(
            "assets/test.svg",
            controller: this.controller,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            if (controller.isCompleted) {
              controller.reverse();
            } else {
              controller.forward();
            }
          },
          child: Icon(Icons.play_arrow),
        ),
      ),
    );
  }
}

4. 动态创建的 Path 对象

你可以直接提供 Path 对象来创建动画。这些对象可以在动画过程中动态更改。

import 'package:flutter/material.dart';
import 'package:drawing_animation/drawing_animation.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool run = true;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Drawing Animation Example')),
        body: Center(
          child: AnimatedDrawing.paths(
            [
              // Path objects
              Path()..addRect(Rect.fromLTWH(50, 50, 100, 100)),
              Path()..addOval(Rect.fromLTWH(200, 200, 100, 100)),
            ],
            paints: [
              Paint()..color = Colors.red..style = PaintingStyle.stroke..strokeWidth = 5,
              Paint()..color = Colors.blue..style = PaintingStyle.stroke..strokeWidth = 5,
            ],
            run: this.run,
            duration: Duration(seconds: 3),
            onFinish: () => setState(() {
              this.run = false;
            }),
          ),
        ),
      ),
    );
  }
}

配置选项

以下是一些常用的配置选项及其视觉效果:

字段 类型 示例
lineAnimation LineAnimation.oneByOne oneByOne
lineAnimation LineAnimation.allAtOnce allAtOnce
animationOrder PathOrders.original original
animationOrder PathOrders.bottomToTop bottomToTop
animationOrder PathOrders.decreasingLength decreasingLength
animationOrder PathOrders.increasingLength increasingLength
animationOrder PathOrders.leftToRight leftToRight
animationOrder PathOrders.rightToLeft rightToLeft
animationOrder PathOrders.topToBottom topToBottom
animationCurve Curves.linear linear
animationCurve Curves.elasticOut elasticOut
animationCurve Curves.bounceInOut bounceInOut
animationCurve Curves.decelerate decelerate

支持的 SVG 规范

  • 仅支持路径元素:目前只支持 <path> 元素,其他元素(如圆、矩形等)暂不支持。
  • 属性
    • stroke:仅支持十六进制颜色,不支持透明度。
    • stroke-width
    • style:仅支持上述两个字段。
  • 不支持变换:目前不支持任何变换操作。

如何使用自己的 SVG 文件?

  1. 选择所有对象并取消分组,直到没有分组为止(Ctrl+U)。
  2. 将选择转换为路径:Path > Object to Path,然后保存。
  3. 使用 svgo 或其在线版本 svgomg 去除变换。
  4. 如果仍然有问题,请提交 issue。

示例

  • Example_01:使用 AnimatedDrawing.svgAnimatedDrawing.paths 设置简化版动画。
  • Example_02:使用自定义动画控制器设置 AnimatedDrawing
  • Example_03:使用英国图书馆提供的旧书扫描矢量化图形的小型艺术展示应用。
  • Example_04:展示如何使用 debug 字段创建高分辨率 GIF。

待办事项

  • 提高测试覆盖率
  • 改进 SVG 解析能力
    • 支持圆、矩形等更多元素
    • 支持更复杂的颜色解析,包括透明度
    • 替换现有的 SVG 解析逻辑,使用成熟的解析库如 flutter_svg
  • 提供覆盖 AnimatedDrawing.svg 的颜色/画笔等选项
  • 定义一个 PathOrder,保持每个路径并仅相对排序
  • 改进 AnimatedDrawing.paths 的性能
  • 展示:以不同方式写入 “drawing_animation” 并创建 GIF
  • 展示:使用 L-系统创建分形

致谢

感谢 maxwellitovivus 项目为本库提供了初始灵感,感谢 dnfieldpath_parsing 库。感谢英国图书馆提供的旧书扫描矢量化图形。


更多关于Flutter绘图动画插件drawing_animation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter绘图动画插件drawing_animation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的drawing_animation插件的使用,这里提供一个基本的代码案例来展示如何使用这个插件进行绘图动画。drawing_animation插件允许你在Flutter应用中创建和控制绘图动画。

首先,确保你已经在pubspec.yaml文件中添加了drawing_animation依赖:

dependencies:
  flutter:
    sdk: flutter
  drawing_animation: ^最新版本号  # 替换为当前最新版本号

然后运行flutter pub get来安装依赖。

以下是一个简单的代码示例,展示如何使用drawing_animation插件绘制一个动画路径:

import 'package:flutter/material.dart';
import 'package:drawing_animation/drawing_animation.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Drawing Animation Example'),
        ),
        body: Center(
          child: DrawingAnimationExample(),
        ),
      ),
    );
  }
}

class DrawingAnimationExample extends StatefulWidget {
  @override
  _DrawingAnimationExampleState createState() => _DrawingAnimationExampleState();
}

class _DrawingAnimationExampleState extends State<DrawingAnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);

    _animation = Tween<double>(begin: 0, end: 1).animate(_controller);
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder<double>(
      animation: _animation,
      builder: (context, snapshot, animationValue) {
        return DrawingAnimation(
          size: Size(300, 300),
          drawings: [
            Drawing.path(
              path: Path()
                ..moveTo(50, 150)
                ..quadraticBezierTo(
                  150 * animationValue, 50,
                  250, 150,
                ),
              color: Colors.blue,
              strokeWidth: 4.0,
            ),
          ],
        );
      },
    );
  }
}

代码解释

  1. 依赖导入

    • 导入flutter/material.dartdrawing_animation/drawing_animation.dart
  2. 主应用

    • 使用MaterialAppScaffold创建一个简单的应用结构。
  3. 状态管理

    • DrawingAnimationExample是一个有状态的组件,用于管理动画状态。
    • 使用SingleTickerProviderStateMixin来混合动画控制器。
  4. 动画控制器

    • AnimationController控制动画的时长和重复行为。
    • Tween<double>定义了动画值从0到1的变化。
  5. 动画构建

    • AnimatedBuilder<double>监听动画值的变化。
    • DrawingAnimation组件用于绘制动画路径。
    • Drawing.path方法定义了一个二次贝塞尔曲线路径,路径的终点随着动画值的变化而移动。

这个示例展示了如何使用drawing_animation插件来创建一个简单的绘图动画。你可以根据需要调整路径、颜色、动画时长等参数,以实现更复杂的动画效果。

回到顶部