经过之前的一系列文章的学习,相信大家对于如何制作手绘板已经有了初步了了解,这一篇作为阶段性的一篇,也就是将画布作为图片进行保存。
后续想到其它新功能再进行添加。
关于画布保存,最主要的是 CustomPainter 这个类,因为它就是在画布上绘画的了,所以我们先存储起来:
class PaintedBoardProvider extends ChangeNotifier {
// 存储当前的绘制
CustomPainter? customPainter;
class MyPainter extends CustomPainter {
MyPainter(this.paintedBoardProvider)
: super(repaint: paintedBoardProvider){
paintedBoardProvider.customPainter = this; // <- 新增
}
然后我还写了个工具类,用于把 CustomPainter 里面的绘画内容保存为 Image:
class ImageUtils{
/// 获取绘制的图片
static Future getRenderedImg(CustomPainter? customPainter, Size size) {
if (customPainter != null) {
ui.PictureRecorder recorder = ui.PictureRecorder();
Canvas canvas = Canvas(recorder);
customPainter.paint(canvas, size);
return recorder
.endRecording()
.toImage(size.width.floor(), size.height.floor());
}
return Future.value(null);
}
}
思路也是很简单,新建一个 canvas,让 CustomPainter 重新在新的 canvas 上重新绘画一次,然后再进行数据转换即可。
既然我们要保存图片,那我们得先新增一个保存按钮并添加点击事件:
Expanded(
child: GestureDetector(
onTap: () {
ImageUtils.getRenderedImg(
_paintedBoardProvider.customPainter,
_paintedBoardProvider.realCanvasSize)
.then((image) async {
if (image == null) {
return;
} else {
var pngBytes = await image.toByteData(
format: ui.ImageByteFormat.png);
ImageGallerySaver.saveImage(
pngBytes!.buffer.asUint8List());
}
});
},
child: const Center(
child: Text("save"),
),
),
),
在该点击事件中,我使用了 ImageUtils 进行画布保存,但是保存出来的是 Image,所以,这里我使用了一个第三方库 image_gallery_saver 进行图片保存到相册中,使用起来也比较方便,直接保存即可:
ImageGallerySaver.saveImage(
pngBytes!.buffer.asUint8List());
}
若想了解更多该库内容,可以看看:「image_gallery_saver」。
但是这样保存图片还是有点小问题,因为该画布没有绘画背景,所以保存下来的背景是黑色的,那我们就给它新增一个背景效果:
void paint(Canvas canvas, Size size) {
paintedBoardProvider.realCanvasSize = size;
canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), Paint()..color=Colors.redAccent); // <- 新增
canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
这里我为了显眼,弄了个红色,大家可以弄个白色什么的。
剩下就是该系列源码了:手绘板制作
感谢大家,虽然没人看 😂