|
@@ -0,0 +1,156 @@
|
|
|
+import 'dart:convert';
|
|
|
+
|
|
|
+import 'package:fis_common/event/event_type.dart';
|
|
|
+import 'package:fis_lib_business_components/components/white_board/color_util.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.userId,
|
|
|
+ required this.paintType,
|
|
|
+ required this.sendData,
|
|
|
+ required this.onReceiveData,
|
|
|
+ required this.onClearCanavs,
|
|
|
+ });
|
|
|
+
|
|
|
+ /// 用户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;
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ widget.onReceiveData.addListener((sender, data) {
|
|
|
+ _onReceiveData(data);
|
|
|
+ });
|
|
|
+ widget.onClearCanavs.addListener((sender, userId) {
|
|
|
+ _clearUserLines(userId);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @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) {
|
|
|
+ _sentData();
|
|
|
+ myPen.doneLine();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 发送数据
|
|
|
+ void _sentData() {
|
|
|
+ List<List<double>> pathIdLists = [];
|
|
|
+ for (int i = 0; i < myPen.activeLine.points.length; i++) {
|
|
|
+ pathIdLists.add(myPen.activeLine.points[i].toList());
|
|
|
+ }
|
|
|
+ widget.sendData(jsonEncode({
|
|
|
+ "action": "add",
|
|
|
+ "type": widget.paintType.index,
|
|
|
+ "userId": widget.userId,
|
|
|
+ "lineId": "",
|
|
|
+ "pathIdList": jsonEncode(pathIdLists),
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 接收数据
|
|
|
+ void _onReceiveData(String crossData) async {
|
|
|
+ var data = jsonDecode(crossData);
|
|
|
+ List<dynamic> pathIdList = jsonDecode(data["pathIdList"]);
|
|
|
+ Line line = Line(
|
|
|
+ color: ColorUtil.generateColor(data["userId"]),
|
|
|
+ strokeWidth: strokeWidth,
|
|
|
+ userId: data["userId"],
|
|
|
+ );
|
|
|
+
|
|
|
+ myPen.pushLine(line);
|
|
|
+
|
|
|
+ for (int i = 0; i < pathIdList.length; i++) {
|
|
|
+ myPen.pushPoint(Point.fromList(
|
|
|
+ pathIdList[i],
|
|
|
+ ));
|
|
|
+ await Future.delayed(const Duration(milliseconds: 2));
|
|
|
+ }
|
|
|
+ myPen.doneLine();
|
|
|
+ }
|
|
|
+
|
|
|
+ void _clearUserLines(String userId) {
|
|
|
+ myPen.clearCurrectUserLines(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ void _onPanCancel() {
|
|
|
+ myPen.removeEmpty();
|
|
|
+ }
|
|
|
+}
|