用Flutter实现一个涂鸦和加水印功能

栏目: Android · 发布时间: 6年前

内容简介:GitHub地址:先上效果图:这次的想法是移植自项目中的一个小功能:截屏当前页面,添加涂鸦功能后,分享给第三方APP。分享功能我们暂不讨论,使用插件可以轻松完成,重点是截屏+涂鸦+图片保存。

本文涉及的知识点:截图、图片保存、根据用户手势实时绘制canvas。

GitHub地址: github.com/yumi0629/Fl…

先上效果图:

用Flutter实现一个涂鸦和加水印功能
用Flutter实现一个涂鸦和加水印功能

需求分析

这次的想法是移植自项目中的一个小功能:截屏当前页面,添加涂鸦功能后,分享给第三方APP。分享功能我们暂不讨论,使用插件可以轻松完成,重点是截屏+涂鸦+图片保存。

具体实现思路是:截取当前屏幕内容,保存至APP缓存目录,涂鸦页面再去读取文件,依然是使用CustomerPaint实现根据用户手势实时绘制,最后将用户涂鸦部分与原图片组合保存至本地。给图片加水印的实现其实就是截屏,因为截取当前屏幕内容实际上也是将Widget转化为byteData再转化为File的过程。

截屏并保存

Flutter提供了一个 RepaintBoundary Widget来实现截图的功能,用 RepaintBoundary 包裹需要截取的部分, RenderRepaintBoundary 可以将 RepaintBoundary 包裹的部分截取出来;然后通过 boundary.toImage() 方法转化为 ui.Image 对象,再使用 image.toByteData() 将image转化为 byteData ;最后通过 File().writeAsBytes() 存储为文件对象:

RepaintBoundary(
                  key: _repaintKey,
                  child: Stack(
                    alignment: Alignment.bottomRight,
                    children: <Widget>[
                      Image.asset(
                        'images/food01.jpeg',
                        fit: BoxFit.cover,
                      ),
                      Icon(Icons.translate,),
                    ],
                  ),
                )
复制代码
RenderRepaintBoundary boundary =
                    _repaintKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
File(tempPath).writeAsBytes(pngBytes);
复制代码

需要注意的地方:

  • 记住给 RepaintBoundary 添加一个 key ,因为我们需要通过这个 key 来找到当前的 RenderObject ,生成一个 RenderRepaintBoundary 对象;
  • image.toByteData(format: format) 可以自定义存储格式,一般图片为 png 格式,但是要注意,如果你的 RepaintBoundary 包裹的部分没有设置背景色,那么存储出来的图片可能会有背景色缺失的问题, boundary.toImage() 并不会自动添加一个你想要的白色背景,这种情况在截取 Text 的时候会尤其明显。

Flutter中获取存储路径

我们可以通过官方插件 path_provider 来获取APP的内部和外部存储路径:

  • Directory tempDir = await getTemporaryDirectory() ,等同于iOS中的 NSCachesDirectory API和Android中的 getCacheDir API;
  • Directory externalDir = await getExternalStorageDirectory() ,不支持iOS(会抛出UnsupportedError),等同于Android中的 getExternalStorageDirectory API;
  • Directory applicationDir = await getApplicationDocumentsDirectory() ,等同于iOS中的 NSDocumentsDirectory API和Android中的 AppData 目录;

要注意的是 getExternalStorageDirectory() 方法,大多数情况下是访问SDCard路径,因此即使在Android中调用,也要注意权限问题,推荐使用 permission_handler 插件。 还有就是存储文件的时候要养成一个好习惯,先判断下父目录是否存在:

void _saveImage(Uint8List uint8List, Directory dir, String fileName) async {
  bool isDirExist = await Directory(dir.path).exists();
  if (!isDirExist) Directory(dir.path).create();
  ······
  File(tempPath).writeAsBytes(uint8List);
}
复制代码

涂鸦

通过 GestureDetector 包裹需要绘制的区域,收集用户的手势路径信息,通过 canvas.drawLine() 方法来绘制路径:

List<Offset> points = [];

GestureDetector(
          onPanStart: (details) {
          },
          onPanUpdate: (details) {
            RenderBox referenceBox = context.findRenderObject();
            Offset localPosition =
                referenceBox.globalToLocal(details.globalPosition);
            state(() {
              points.add(localPosition);
            });
          },
          onPanEnd: (details) {
          },
        )
复制代码
for (int i = 0; i < points.length - 1; i++) {
        if (points[i] != null && points[i + 1] != null)
          canvas.drawLine(points[i], points[i + 1], _linePaint);
      }
复制代码

为什么不直接用 canvas.drawPoints() 方法呢?

即使将 PointMode 设置为 PointMode.lines ,你会发现,绘制出来的点集合并不是无缝连接在一起的,看起来就像是虚线一样:

用Flutter实现一个涂鸦和加水印功能

因此我们还是使用 drawLine() 强行将所有点连接起来。

用户绘制完成后,依然是使用 RepaintBoundary

来保存图片就可以啦~~~


以上所述就是小编给大家介绍的《用Flutter实现一个涂鸦和加水印功能》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Domain-Driven Design Distilled

Domain-Driven Design Distilled

Vaughn Vernon / Addison-Wesley Professional / 2016-6-2 / USD 36.99

Domain-Driven Design (DDD) software modeling delivers powerful results in practice, not just in theory, which is why developers worldwide are rapidly moving to adopt it. Now, for the first time, there......一起来看看 《Domain-Driven Design Distilled》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具