123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- import 'dart:convert';
- import 'package:fis_common/event/event_type.dart';
- import 'package:fis_lib_business_components/components/white_board/utils.dart';
- import 'package:fis_lib_business_components/components/white_board/structure.dart';
- import 'package:fis_lib_business_components/components/white_board/white_board_painter.dart';
- import 'package:flutter/material.dart';
- class WhiteBoard extends StatefulWidget {
- const WhiteBoard({
- key,
- required this.initData,
- required this.userId,
- required this.paintType,
- required this.sendData,
- required this.onReceiveData,
- required this.onClearCanavs,
- });
- /// 初始画板副本数据
- final List<String> initData;
- /// 用户id
- final String userId;
- /// 当前绘制模式
- final PaintType paintType;
- /// 发送数据(接 JsonRPC)
- final void Function(String data) sendData;
- /// 接收数据(接 WebSocket)
- final FEventHandler<String> onReceiveData;
- /// 画布清除事件
- final FEventHandler<String> onClearCanavs;
- @override
- State<WhiteBoard> createState() => _WhiteBoardState();
- }
- class _WhiteBoardState extends State<WhiteBoard> {
- /// 画布尺寸
- late double canvasWidth = 0.0;
- late double canvasHeight = 0.0;
- /// 当前用户的画笔
- WhiteBoardPen myPen = WhiteBoardPen();
- /// 当前用户的画笔颜色
- Color get myPenColor => ColorUtil.generateColor(widget.userId);
- /// 固定的画笔粗细
- static const double strokeWidth = 3.0;
- /// 异步绘制队列
- List<String> _asyncDrawQueue = [];
- /// 异步绘制锁
- bool _asyncDrawLock = false;
- @override
- void initState() {
- super.initState();
- widget.onReceiveData.addListener((sender, data) {
- _onReceiveDrawData(data);
- });
- widget.onClearCanavs.addListener((sender, userId) {
- _clearUserLines(userId);
- });
- /// 加载完后一帧绘制初始数据
- WidgetsBinding.instance.addPostFrameCallback((_) {
- _paintInitData();
- });
- }
- @override
- Widget build(BuildContext context) {
- canvasWidth = MediaQuery.of(context).size.width;
- canvasHeight = MediaQuery.of(context).size.height;
- return MouseRegion(
- cursor: SystemMouseCursors.click,
- child: GestureDetector(
- onPanDown: _onPanDown,
- onPanUpdate: _onPanUpdate,
- onPanEnd: _onPanEnd,
- onPanCancel: _onPanCancel,
- onDoubleTap: myPen.clear,
- child: CustomPaint(
- size: MediaQuery.of(context).size,
- painter: WhiteBoardPainter(
- pen: myPen,
- width: canvasWidth,
- height: canvasHeight,
- ),
- ),
- ),
- );
- }
- /// 按下时,生成新的线实体
- void _onPanDown(DragDownDetails details) {
- Line line = Line(
- color: myPenColor,
- strokeWidth: strokeWidth,
- paintType: widget.paintType,
- userId: widget.userId,
- );
- myPen.pushLine(line);
- }
- /// 拖动时,生成新的点实体,加入到当前线实体中
- void _onPanUpdate(DragUpdateDetails details) {
- myPen.pushPoint(Point.fromOffset(
- details.localPosition,
- canvasWidth,
- canvasHeight,
- ));
- }
- /// 抬起时,发送数据
- void _onPanEnd(DragEndDetails details) {
- _sentDrawAction();
- myPen.doneLine();
- }
- /// 绘制初始数据
- void _paintInitData() {
- for (int i = 0; i < widget.initData.length; i++) {
- _onReceiveDrawDataImmediately(widget.initData[i]);
- }
- }
- /// 发送绘制指令
- void _sentDrawAction() {
- List<List<double>> pointsList = [];
- for (int i = 0; i < myPen.activeLine.points.length; i++) {
- pointsList.add(myPen.activeLine.points[i].toList());
- }
- widget.sendData(jsonEncode({
- "u_Id": widget.userId, // 用户id
- "l_Id": "", // 线id
- "points": PointsUtil.compressPointsList(pointsList),
- }));
- }
- /// 接收绘制数据【如果存在数据正在绘制,其他的加入绘制队列,等待当前绘制完成继续绘制】
- void _onReceiveDrawData(String jsonData) async {
- if (_asyncDrawLock) {
- _asyncDrawQueue.add(jsonData);
- return;
- }
- _asyncDrawLock = true;
- var data = jsonDecode(jsonData);
- List<dynamic> pointsList = PointsUtil.decompressPointsList(data["points"]);
- Line line = Line(
- color: ColorUtil.generateColor(data["u_Id"]),
- strokeWidth: strokeWidth,
- userId: data["u_Id"],
- );
- myPen.pushLine(line);
- for (int i = 0; i < pointsList.length; i++) {
- myPen.pushPoint(Point.fromList(
- pointsList[i],
- ));
- await Future.delayed(const Duration(milliseconds: 2));
- }
- myPen.doneLine();
- _asyncDrawLock = false;
- /// 判断如果队列存在数据,继续绘制
- if (_asyncDrawQueue.isNotEmpty) {
- _onReceiveDrawData(_asyncDrawQueue.removeAt(0));
- }
- }
- /// 接收绘制数据立即绘制,无 Future.delayed
- void _onReceiveDrawDataImmediately(String jsonData) {
- var data = jsonDecode(jsonData);
- List<dynamic> pointsList = PointsUtil.decompressPointsList(data["points"]);
- Line line = Line(
- color: ColorUtil.generateColor(data["u_Id"]),
- strokeWidth: strokeWidth,
- userId: data["u_Id"],
- );
- myPen.pushLine(line);
- for (int i = 0; i < pointsList.length; i++) {
- myPen.pushPoint(Point.fromList(
- pointsList[i],
- ));
- }
- myPen.doneLine();
- }
- void _clearUserLines(String userId) {
- myPen.clearCurrectUserLines(userId);
- }
- void _onPanCancel() {
- myPen.removeEmpty();
- }
- }
|