Flutter文本转路径插件text_to_path_maker的使用

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

Flutter文本转路径插件text_to_path_maker的使用

Text to Path Maker 插件简介

Text to Path Maker 是一个纯Flutter和Dart包,它允许你将文本(字符和图标)转换为路径。它可以生成SVG路径字符串和Flutter Path 对象。

此外,这个包还提供了一系列方法来动画化这些路径。在该包的核心是一个用纯Dart编写的.ttf文件解析器。你可以用它来读取TrueType字体文件中的字体表。

example

开始使用

1. 解析字体资源

你需要始终通过调用PMFontReader类中可用的parseTTFAsset()方法来解析你的字体资源。目前,仅支持.ttf文件。一旦字体被解析,你将获得一个PMFont对象。你可以调用它的generatePathForCharacter()方法将任何字符转换为Path对象。请注意,此方法期望你传递字符的字符代码。

// 加载字体文件并解析
rootBundle.load("assets/font2.ttf").then((ByteData data) {
  var reader = PMFontReader();
  myFont = reader.parseTTFAsset(data);
});

2. 生成字符路径

解析完字体后,可以使用generatePathForCharacter()方法根据字符编码生成路径,并且通常需要使用PMTransform.moveAndScale()方法对路径进行位置和缩放调整,因为默认情况下路径可能非常大。

myPath1 = myFont.generatePathForCharacter(101); // 'e'的字符编码为101
myPath1 = PMTransform.moveAndScale(myPath1, -130.0, 180.0, 0.1, 0.1);

3. 动画化路径

如果你想要动画化路径,则必须调用PMPieces.breakIntoPieces()方法。此方法根据指定的精度将路径分割成小路径。当顺序渲染这些小路径时,将创建字符被绘制的错觉。

path1Pieces = PMPieces.breakIntoPieces(myPath1, 0.01);

4. 渲染路径

最后,可以通过CustomPaint和自定义的CustomPainter来渲染路径动画。

CustomPaint(
  painter: PMPainter(path1Pieces.paths[z],
      indicatorPosition: path1Pieces.points[z],
      radius: 5.0,
      indicator: indicator)
),

完整示例代码

以下是一个完整的示例demo,展示了如何加载字体、生成路径、创建动画并渲染:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:text_to_path_maker/text_to_path_maker.dart';
import 'dart:typed_data';

void main() {
  runApp(const Home());
}

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _Home();
}

class _Home extends State<Home> with SingleTickerProviderStateMixin {
  late PMFont myFont;
  late Path myPath1;
  late PMPieces path1Pieces;

  late Animation<int> animation;
  late AnimationController controller;

  var z = 0;
  var ready = false;

  late Paint indicator;

  @override
  void initState() {
    super.initState();

    indicator = Paint()
      ..style = PaintingStyle.fill
      ..color = const Color.fromRGBO(255, 0, 0, 1.0);

    rootBundle.load("assets/font2.ttf").then((ByteData data) {
      var reader = PMFontReader();
      myFont = reader.parseTTFAsset(data);
      myPath1 = myFont.generatePathForCharacter(101); // 'e'的字符编码为101
      myPath1 = PMTransform.moveAndScale(myPath1, -130.0, 180.0, 0.1, 0.1);
      path1Pieces = PMPieces.breakIntoPieces(myPath1, 0.01);

      controller = AnimationController(
          vsync: this, duration: const Duration(seconds: 2));

      animation = IntTween(begin: 0, end: path1Pieces.paths.length - 1)
          .animate(controller);

      animation.addListener(() {
        setState(() {
          z = animation.value;
        });
      });

      setState(() {
        ready = true;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text("Text To Path Example")),
        body: Container(
          padding: const EdgeInsets.all(16),
          child: Column(
            children: [
              Row(
                children: [
                  ElevatedButton(
                    onPressed: ready ? () => controller.forward() : null,
                    child: const Text("Forward"),
                  ),
                  const Spacer(),
                  ElevatedButton(
                    onPressed: ready ? () => controller.reverse() : null,
                    child: const Text("Reverse"),
                  ),
                ],
              ),
              Expanded(
                child: ready
                    ? CustomPaint(
                        size: Size.infinite,
                        painter: PMPainter(
                            path1Pieces.paths[z],
                            indicatorPosition: path1Pieces.points[z],
                            radius: 5.0,
                            indicator: indicator))
                    : const Center(child: Text("Loading")),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意事项

  • 该包仍在开发中,虽然它与大多数字体配合使用效果不错,但不能保证处理每一个字体。
  • 已经测试了Roboto、FontAwesome和Material Icons等字体。如果发现错误,可以在项目的GitHub仓库中提交问题。

通过上述步骤,你应该能够成功地将文本转换为路径并在Flutter应用中进行动画化。希望这对你有所帮助!


更多关于Flutter文本转路径插件text_to_path_maker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文本转路径插件text_to_path_maker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用text_to_path_maker插件的一个代码示例。这个插件允许你将文本转换为路径数据,这对于创建自定义文本渲染或动画非常有用。

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

dependencies:
  flutter:
    sdk: flutter
  text_to_path_maker: ^最新版本号  # 请替换为最新的版本号

然后运行flutter pub get来获取依赖。

接下来,你可以在你的Dart文件中使用text_to_path_maker。以下是一个完整的示例,展示如何将文本转换为路径并在Canvas上绘制它:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Text to Path Maker Example'),
        ),
        body: Center(
          child: CustomTextPathWidget(text: 'Hello, Flutter!'),
        ),
      ),
    );
  }
}

class CustomTextPathWidget extends StatelessWidget {
  final String text;

  CustomTextPathWidget({required this.text});

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size.infinite,
      painter: TextPathPainter(text: text),
    );
  }
}

class TextPathPainter extends CustomPainter {
  final String text;

  TextPathPainter({required this.text});

  @override
  void paint(Canvas canvas, Size size) {
    final TextPainter textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: TextStyle(
          color: Colors.black,
          fontSize: 24.0,
        ),
      ),
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    )..layout(minWidth: 0, maxWidth: size.width);

    final List<Offset> textPositions = textPainter.runPositions.expand((rp) {
      return rp.glyphs.map((glyph) => rp.offset + glyph.offset);
    }).toList();

    final TextToPathMaker textToPathMaker = TextToPathMaker(textPainter);
    final Path textPath = textToPathMaker.createPath();

    final Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    canvas.drawPath(textPath, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,它包含一个自定义的CustomTextPathWidget。这个widget使用CustomPaint来绘制文本路径。

TextPathPainter类是我们自定义的CustomPainter,它使用TextPainter来获取文本的位置和布局信息,然后使用TextToPathMaker将这些信息转换为路径。最后,我们使用Canvas.drawPath方法绘制这个路径。

请注意,这个示例假设text_to_path_maker插件提供了一个TextToPathMaker类,该类能够将TextPainter的信息转换为路径。然而,实际的text_to_path_maker插件的API可能有所不同,因此你可能需要参考该插件的文档来调整代码。如果text_to_path_maker没有提供直接的TextToPathMaker类,你可能需要自己实现文本到路径的转换逻辑。

回到顶部