Flutter CustomPainter实现手写签名并保存为图片且去掉多余空白

本文介绍了如何在Flutter中实现手写签名功能,通过GestureDetector监听手势绘制路径,CustomPainter进行绘制。接着,文章详细讲述了如何保存签名图像并去除背景多余空白,提供了一个完整的示例代码,包括签名效果展示、绘制过程以及图片保存方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 手写签名效果图

在这里插入图片描述


2 实现手写签名

2.1 使用GestureDetector监听手势并记录

Flutter提供的GestureDetector可以监听手势变化,我们可以将签名时的手势滑动路径记录下来,然后再绘制。

  • 手从开始移动到离开屏幕为 写了一笔画,由Path来记录笔画的路径。
  • List<Path> 来记录所有的笔画,凑成完整的签名。
class HandwrittenSignatureWidget extends StatefulWidget {
   
  const HandwrittenSignatureWidget({
   Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _HandwrittenSignatureWidgetState();
}

class _HandwrittenSignatureWidgetState
    extends State<HandwrittenSignatureWidget> {
   
  // 记录一次 不间断的手势路径 即记录一次 笔画
  Path? _path;

  // 在一次不间断的移动过程中 记录上一坐标点 用于在前后2点之间绘制贝塞尔曲线
  Offset? _previousOffset;

  // 记录所有的笔画 可拼凑成完整字
  final List<Path?> _pathList = [];

  @override
  Widget build(BuildContext context) {
   
    return GestureDetector(
      //手解除到屏幕,在开始移动了
      onPanStart: (details) {
   
        // 获取当前的坐标
        var position = details.localPosition;
        // 每次重新开始时就是新的Path对象
        _path = Path()..moveTo(position.dx, position.dy);
        _previousOffset = position;
      },
      //持续移动中
      onPanUpdate: (details) {
   
        // 获取当前的坐标
        var position = details.localPosition;
        var dx = position.dx;
        var dy = position.dy;

        final previousOffset = _previousOffset;
        //如果没有上一坐标点
        if (previousOffset == null) {
   
          _path?.lineTo(dx, dy);
        } else {
   
          var previousDx = previousOffset.dx;
          var previousDy = previousOffset.dy;
          // 已贝塞尔曲线的方式连线
          _path?.quadraticBezierTo(
            previousDx,
            previousDy,
            (previousDx + dx) / 2,
            (previousDy + dy) / 2,
          );
        }
        _previousOffset = position;
      },
      // 手停止了移动 离开了屏幕
      onPanEnd: (details) {
   
        // 记录笔画,然后清空临时变量
        _pathList.add(_path);
        _previousOffset = null;
        _path = null;
      },
    );
  }
}

2.2 使用CustomPainter绘制手写签名

绘制手写签名需要用到 CustomPaint 与 CustomPainter

  • CustomPaint 是一个Widget ,提供了绘制时所需的画布。
  • CustomPainter 一个用于实现CustomPaint绘制的接口,需要实现此接口来进行自定义绘制。

首先自定义CustomPainter

class SignaturePainter extends CustomPainter {
   
  // 绘制签名需要 历史的笔画
  final List<Path?> pathList;

  // 当前正在写 的笔画
  final Path? currentPath;

  SignaturePainter(this.pathList, this.currentPath);

  // 设置画笔的属性
  final _paint = Paint()
    ..color = Colors.black
    ..style = PaintingStyle.stroke
    ..strokeCap = StrokeCap.round // 线条两端的形状
    ..strokeJoin = StrokeJoin.round // 2条线段连接处的形状
    ..strokeWidth = 2 //线宽
    ..isAntiAlias = true; //抗锯齿

  @override
  void paint(Canvas canvas, Size size) {
   
    // 绘制以前写过的笔画
    for (Path? path in pathList) {
   
      _drawLine(canvas, path);
    }
    // 绘制当前正在写的笔画
    _drawLine(canvas, currentPath);
  }

  void _drawLine(Canvas canvas, Path? path) {
   
    if (path ==
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值