FlutterWeb-07-自定义view绘制-widget保存为图片

1,035 阅读2分钟

本文代码:gitee.com/gyy_xiaobai…

目标:
1,我们用flutter实现一个快递标签的绘制
2,将绘制的标签,保存为图片,存到电脑本地

00.jpg

一,自定义view,绘制快递标签

1,标签容器

Container(
  color: Colors.grey.shade200,
  width: maxWidth_printer,
  height: maxHeight_printer,
  child: CustomPaint(
    foregroundPainter: GoodsLabelHelp(),
  ),
),

主要代码在GoodsLabelHelp中,即自定义的CustomPainter

2,CustomPainter中绘制直线

// Offset(startX,startY),Offset(endX,endY)
canvas.drawLine(Offset(0, 0), Offset(200, 0), paint);

第一个Offset的参数是,起始点的坐标,第二个Offset的参数是,结束点的坐标

3,CustomPainter中绘制文字

TextPainter(
  text: const TextSpan(text: "客户存根", style: TextStyle(color: Colors.black, fontSize: 13)),
    textDirection: TextDirection.ltr)
//layout(最大宽度,最小宽度)
  ..layout(maxWidth: maxWidth_printer, minWidth: minWidth)
//Offset(x坐标, y坐标)
  ..paint(canvas, Offset(0, height));

Offset(x, y):是文字的起始坐标

maxWidth:文字宽度所占空间,超过宽度会换行

4,绘制横向的条码,我们使用下面这个库,很容易的可以绘制条形码

barcode_widget: ^2.0.2

5,完整的绘制代码,在项目中,感兴趣的clone下来查看

二,重点了解下,flutterWeb如何将widget转为图片输出到pc本地

1,添加依赖(用来将widget处理成Uint8List或ui.Image)

screenshot: ^1.2.3

2,Screenshot的使用,需要传一个child(widget),和一个controller,就可以调用controller的方法,将child转换为Uint8List或ui.Image

Screenshot({
  Key? key,
  required this.child,
  required this.controller,
}) : super(key: key);

3,调用controller.capture

void saveImage() async{
  //capture方法返回的是Uint8List类型的数据
  printController.capture(delay: Duration(milliseconds: 10))
      .then((capturedImage) async {
        //这个方法是重点,实现将Uint8List类型的数据转换为 png或jpg的图片数据
    saveUint8ListImage(capturedImage, "biaoqian");
  }).catchError((onError) {
    debugPrint(onError);
  });
}

4,看saveUint8ListImage

11.png

5,看imageSaver_web.dart文件的ImageSaver.save方法

import 'dart:async';
import 'dart:typed_data';
import 'package:js/js.dart';
@JS()
external void _exportRaw(String key, Uint8List value);
///web - 保存和选择照片
class ImageSaver {
  static Future<String> save(String name, Uint8List fileData) async {
    _exportRaw(name, fileData);
    return name;
  }
}

最终,我们会调用js的原生方法,_exportRaw来实现图片的导出

6,_exportRaw,在web_plugin.js文件中,是js方法(在index.html中,导入了web_plugin.js)

//导出照片
function _exportRaw(name, data) {
  var urlObject = window.URL || window.webkitURL || window;
  var export_blob = new Blob([data]);
  var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
  save_link.href = urlObject.createObjectURL(export_blob);
  save_link.download = name;
  fake_click(save_link);
}

//模拟点击事件
function fake_click(obj) {
  var ev = document.createEvent("MouseEvents");
  ev.initMouseEvent(
      "click", true, false, window, 0, 0, 0, 0, 0
      , false, false, false, false, 0, null
      );
  obj.dispatchEvent(ev);
}

三,总结:保存图片,最终是调用了js原生方法,过程是有点绕,这也是flutterWeb开发,在web平台上的小不爽