[译]不错的 Flutter 签名插件 signature

777 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情


signature | Flutter Package (flutter-io.cn)

译时版本:5.2.1


signature

提供性能优化的签名 Canvas ,可以设置自定义样式、边界和初始状态。 用 Fluter 原生实现,支持所有平台。

选择该插件的理由

在创建该插件之时,以下问题还没有可用的方案:

  • 在多种设备上运行
  • 可设置 Canvas 的边界
  • 可使用提前保存的状态初始化

用法

要使用该插件,在 pubspec.yaml 中添加 signature 作为依赖。

示例

// 导入包
import 'package:signature/signature.dart';

// 初始化controller。它包含 签名的点阵、笔迹的粗细和画笔的颜色。
// 它可用于和组件交互。
final SignatureController _controller = SignatureController(
    penStrokeWidth: 5,
    penColor: Colors.red,
    exportBackgroundColor: Colors.blue,
);

// 初始化。结果是一个组件,所以可以直接在 build 方法中使用。
var _signatureCanvas = Signature(
  controller: _controller,
  width: 300,
  height: 300,
  backgroundColor: Colors.lightBlueAccent,
);

// 清空 Canvas
_controller.clear();

// 导出字节为 PNG
// 导入的图片会限制在绘制区域
_controller.toPngBytes();

// isEmpty/isNotEmpty 可用于检查是否提供了签名
_controller.isNotEmpty; // 提供了签名时为 True
_controller.isEmpty; // 没有提供签名时为 True

// 导出点阵 (2D的点阵大体就是 Canvas 上看到的内容)
var exportedPoints = _controller.points;

// 导出点阵 可用于初始化上面的 Controller
final SignatureController _controller = SignatureController(points: exportedPoints);

signature.gif


使用手记

在使用该插件时,发现导出图片时感觉清晰度不够,也没深入研究原因。
然后自己定制了一下。

  1. 添加一个全局Key,不过 Flutter 不建议这么使用。

    signature.dart:

    /// 导出用全局 Key
    final GlobalKey keyRepaintBoundary;
    
    /// constructor
    const Signature({
      required this.keyRepaintBoundary,
      required this.controller,
      Key? key,
      this.backgroundColor = Colors.grey,
      this.dynamicPressureSupported = false,
      this.width,
      this.height,
    }) : super(key: key);
    
  2. 设置 RepaintBoundary 的 key 为上面的全局 Key。

    signature.dart:

    child: RepaintBoundary(
      key: widget.keyRepaintBoundary,
      child: CustomPaint(
        painter: _SignaturePainter(widget.controller),
        child: ConstrainedBox(
          constraints: BoxConstraints(
              minWidth: maxWidth, minHeight: maxHeight, maxWidth: maxWidth, maxHeight: maxHeight),
        ),
      ),
    )),
    
  3. 导出图片的地方,这里是导出为 Base64 编码后的数据。

    keyRepaintBoundary 是设定给 Signature 组件的 keyRepaintBoundary。
    最后的 imgData 即是 Base64 编码后的数据。

    if(keyRepaintBoundary.currentContext != null) {
      final RenderRepaintBoundary boundary = keyRepaintBoundary.currentContext!
          .findRenderObject() as RenderRepaintBoundary;
      final img = await boundary.toImage(pixelRatio: window.devicePixelRatio);
      final ByteData? bytes = await (img.toByteData(format: ImageByteFormat.png));
      if(bytes!=null) {
        final Uint8List pngBytes = bytes!.buffer.asUint8List();
        final imgData = base64Encode(pngBytes);
      }
    }