You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中能否实现无手写图标的手写式文字动画?

Flutter手写文字动画实现方案

当然可以实现手写式文字动画,和你当前用的逐字符出现的打字动画不同,手写动画是让每个字符的笔画逐笔逐步显现,模拟真实书写的过程。下面给你两种可行的实现方式:

方式一:自定义绘制(更灵活)

通过CustomPaint结合动画控制器,直接控制文字路径的绘制进度,能精准模拟手写效果:

import 'package:flutter/material.dart';

class HandwritingText extends StatefulWidget {
  final String text;
  final TextStyle style;
  final Duration duration;

  const HandwritingText({
    super.key,
    required this.text,
    required this.style,
    this.duration = const Duration(seconds: 3),
  });

  @override
  State<HandwritingText> createState() => _HandwritingTextState();
}

class _HandwritingTextState extends State<HandwritingText> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: widget.duration,
    )..forward();
    _animation = Tween<double>(begin: 0, end: 1).animate(_controller);
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return CustomPaint(
          painter: _HandwritingPainter(
            text: widget.text,
            style: widget.style,
            progress: _animation.value,
          ),
          child: SizedBox(
            width: MediaQuery.of(context).size.width,
            height: widget.style.fontSize! * 1.5,
          ),
        );
      },
    );
  }
}

class _HandwritingPainter extends CustomPainter {
  final String text;
  final TextStyle style;
  final double progress;

  _HandwritingPainter({
    required this.text,
    required this.style,
    required this.progress,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final textSpan = TextSpan(text: text, style: style);
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    )..layout(minWidth: 0, maxWidth: size.width);

    // 模拟逐笔绘制的遮罩效果,更精准的话可拆分笔画路径
    final rect = Rect.fromLTWH(0, 0, textPainter.width * progress, textPainter.height);
    canvas.saveLayer(rect, Paint());
    textPainter.paint(canvas, Offset.zero);
    canvas.restore();
  }

  @override
  bool shouldRepaint(_HandwritingPainter oldDelegate) {
    return oldDelegate.progress != progress ||
        oldDelegate.text != text ||
        oldDelegate.style != style;
  }
}

使用时直接替换你原来的AnimatedTextKit部分:

Center(
  child: SizedBox(
    width: context.width(),
    child: HandwritingText(
      text: APP_NAME_TAG_LINE,
      style: boldTextStyle(size: 26, color: context.primaryColor),
      duration: const Duration(milliseconds: 3000),
    ).paddingLeft(20),
  ),
)

进阶优化提示

如果想要更真实的手写效果,可借助PathMetrics拆分每个字符的笔画路径,根据动画进度逐步绘制每一段路径,完全模拟手写时的笔画顺序和书写节奏。

内容的提问来源于stack exchange,提问作者user21992702

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:17:30