在实现手写的基础上 增加橡皮擦功能
详情见代码

import 'dart:ui';import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:ui' as UI;class HandWrittenBoard extends StatefulWidget {///手写笔颜色final Color? painColor;///手写笔宽度final double? paintWidth;///橡皮final double? clearWidth;final double? clearDx;final double? clearDy;///手写笔控制器final HandWrittenBoardController boardController;const HandWrittenBoard({Key? key,this.painColor,this.clearWidth,this.paintWidth,required this.boardController,this.clearDx,this.clearDy}): super(key: key);@override_HandWrittenBoardState createState() => _HandWrittenBoardState();
}class HandWrittenBoardController extends ChangeNotifier {late BuildContext _context;late List<Stroke?> strokes = [];void bindContext(BuildContext context) {_context = context;}Future<UI.Image>? get uiImage {UI.PictureRecorder recorder = UI.PictureRecorder();Canvas canvas = Canvas(recorder);BoardPainter painter = BoardPainter();Size size = _context.size!;painter.paint(canvas, size);return recorder.endRecording().toImage(size.width.floor(), size.height.floor());}void refStrokes(List<Stroke> newValue) {if (strokes != newValue) {strokes = newValue;}notifyListeners();}void clearBoard() {strokes.clear();notifyListeners();}
}class _HandWrittenBoardState extends State<HandWrittenBoard> {List<Stroke> _strokes = [];@overridevoid initState() {super.initState();widget.boardController.bindContext(context);}void _onUpdate(DragUpdateDetails details) {if (isClear) {dx = details.localPosition.dx;dy = details.localPosition.dy;}setState(() {_strokes.last.path.lineTo(details.localPosition.dx, details.localPosition.dy);});widget.boardController.refStrokes(_strokes);}void _start(double startX, double startY) {if (isClear) {dx = startX;dy = startY;}final newStroke = Stroke(color: widget.painColor!,width: widget.paintWidth!,isClear: isClear,);newStroke.path.moveTo(startX, startY);_strokes.add(newStroke);widget.boardController.refStrokes(_strokes);}late double dx = widget.clearDx! + widget.clearWidth! / 2;late double dy = widget.clearDy! - widget.clearWidth! / 2;bool isClear = false;@overrideWidget build(BuildContext context) {return GestureDetector(onPanUpdate: _onUpdate,onPanStart: (details) => _start(details.localPosition.dx,details.localPosition.dy,),onPanDown: (detail) {Rect rect =Rect.fromCenter(center: Offset(dx, dy), width: 50, height: 50);isClear = rect.contains(detail.localPosition);},child: Stack(children: [CustomPaint(painter: BoardPainter(strokes: _strokes,clearWidth: widget.clearWidth,),size: Size.infinite,),Positioned(child: Container(width: widget.clearWidth,height: widget.clearWidth,color: Colors.red,),left: dx - widget.clearWidth! / 2,top: dy - widget.clearWidth! / 2,),],),);}
}class Stroke {final path = Path();final Color color;final double width;final bool isClear;Stroke({this.color = Colors.black,this.width = 4,this.isClear = false,});
}class BoardPainter extends CustomPainter {BoardPainter({this.strokes,this.clearWidth,});final List<Stroke>? strokes;final double? clearWidth;@overridevoid paint(Canvas canvas, Size size) {canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height));canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height),Paint()..color = Colors.white,);canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());for (final stroke in strokes!) {final paint = Paint()..strokeWidth = stroke.isClear ? clearWidth! : stroke.width..color = stroke.isClear ? Colors.transparent : stroke.color..strokeCap = StrokeCap.round..style = PaintingStyle.stroke..blendMode = stroke.isClear ? BlendMode.clear : BlendMode.srcOver;canvas.drawPath(stroke.path, paint);}canvas.restore();}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}

使用示范

import 'package:flitter_okgo/hand_written_board.dart';
import 'package:flutter/material.dart';class HandWrittenBoardPage extends StatefulWidget {@override_TestPageState createState() => _TestPageState();
}class _TestPageState extends State<HandWrittenBoardPage> {HandWrittenBoardController controller = HandWrittenBoardController();@overridevoid initState() {super.initState();}Widget get initFloatingActionButton {return FloatingActionButton(backgroundColor: Colors.grey,elevation: 1,focusElevation: 1,onPressed: () {controller.clearBoard();},child: Icon(Icons.clear),);}@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: initFloatingActionButton,floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,appBar: AppBar(title: Text("橡皮擦"),),body: HandWrittenBoard(boardController: controller,clearWidth: 50,paintWidth: 5,painColor: Colors.green,clearDx: 0,clearDy: 200,),);}
}

flutter手写板2.0 橡皮擦相关推荐

  1. 【错误记录】Flutter 报错 ( Could not resolve io.flutter:flutter_embedding_debug:1.0.0. )

    文章目录 一. 报错信息 二. 解决方案 三. 备选方案 一. 报错信息 从网上下载了一个 Flutter 工程代码 , 打开时 , 报如下错误 ; Launching lib\main.dart o ...

  2. Flutter实战 | 从 0 搭建「网易云音乐」APP(五、播放功能逻辑)

    本系列可能会伴随大家很长时间,这里我会从0开始搭建一个「网易云音乐」的APP出来. 下面是该APP 功能的思维导图: 前期回顾: 1.Flutter实战 | 从 0 搭建「网易云音乐」APP(一.创建 ...

  3. Flutter实战 | 从 0 搭建「网易云音乐」APP(三、每日推荐、推荐歌单)

    本系列可能会伴随大家很长时间,这里我会从0开始搭建一个「网易云音乐」的APP出来. 下面是该APP 功能的思维导图: 前期回顾: •Flutter实战 | 从 0 搭建「网易云音乐」APP(一.创建项 ...

  4. Flutter:Navigator2.0介绍及使用

    目录 Navigator1.0 Navigator2.0 APP RouteInformationParser RouterDelegate 问题 The Navigator.pages must n ...

  5. Flutter 升级 2.0 填坑指导,带你原地起飞

    作者 | 恋猫de小郭       责编 | 欧阳姝黎 Flutter 2.0 的发布带来了很多的 break change ,特别是新增加的空声明安全,「相信不少大哥尝鲜之后立马反思自己" ...

  6. Flutter 报错:Could not resolve io.flutter:flutter_embedding_debug:1.0.0-ee76268252c22f5c11e82a7b87423c

    报错信息: 解决方法: 打开build.gradle文件buildscript {ext.kotlin_version = '1.3.50'repositories {google()jcenter( ...

  7. Flutter 手写板 签名

    代码如下: import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'dart ...

  8. Flutter升级3.0

      一.升级 步骤如下: 以Android Studio为例, 1.在Terminal执行命令  flutter upgrade --force 2.执行 flutter pub upgrade,如果 ...

  9. Flutter Channel stable, 0.0.0-unknown, on Microsoft Windows [Version 10.0.18362.1016]

    重装以及 到flutter的安装目录执行 git clean -xfd git stash save --keep-index git stash drop git pull flutter doct ...

  10. Flutter 1.0 正式版: Google 的跨平台 UI 工具包

    今天我们非常高兴的宣布,Flutter 的 1.0 版本正式发布!Flutter 是 Google 为您打造的 UI 工具包,帮助您通过一套代码同时在 iOS 和 Android 上构建媲美原生体验的 ...

最新文章

  1. oracle存储换硬盘,Oracle 10g RAC 数据存储更换
  2. 使用QT定时器 隐藏 label
  3. python编写IP地址与十进制IP转换脚本
  4. 弹框位置设置html,JQuery弹出框定位实现方法
  5. 可视化分析WEB访问:logstalgia
  6. bootstrape常用标签_bootstrap_03_常用标签
  7. JavaScript学习总结(13)——JavaScript常用正则表达式
  8. try catch finally的理解
  9. 爱奇艺开播助手Flutter跨平台Hybrid实践\n
  10. 【python】文件打开中文符问题
  11. c++primer 容器算法整理一
  12. java应用程序由若干个_Java应用程序由若干个类所构成,这些类可以在一个源文件中,也可以分布在若干个源文件中。...
  13. IEEE邮件爆出:禁止华为员工审稿,惨遭网友吐槽!
  14. 如何拼接多张图片,多张图片拼接成一张
  15. [内附完整源码和文档] 基于Java的学生学籍管理系统
  16. Cadence 禁止start page的方法
  17. PyTorch—torch.utils.data.DataLoader 数据加载类
  18. 黑科技教程——伪装 sn
  19. 2010数据库大事记
  20. Python爬取网上车市[http://www.cheshi.com/]的数据

热门文章

  1. 锁定计算机后 360wifi,如何使360wifi关闭电脑后继续使?
  2. Adobe Reader 卸载不干净处理方法
  3. linux字符集中文转英文,oracle字符集(英文-中文)转换
  4. C++11新特性——std::bind参数绑定
  5. 四色定理java_java – 四色定理的递归算法
  6. 为开发者而生 | 2021 SuperMap开发者大会议程全公布
  7. red5+obs+ffmpeg 推流实现单方直播 window +linux
  8. matlab中提取公因子化简,利用MATLAB化简表达式或者多项式 | 望天博客
  9. DSP指纹识别系统硬件设计
  10. Nginx配置带www域名转向无www域名