edge_detection_shape.dart 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import 'dart:math';
  2. import 'dart:ui';
  3. import 'package:flutter/material.dart';
  4. import '../edge_detection.dart';
  5. import '../edge_painter.dart';
  6. import 'magnifier.dart';
  7. import 'touch_bubble.dart';
  8. class EdgeDetectionShape extends StatefulWidget {
  9. const EdgeDetectionShape(
  10. {Key? key,
  11. required this.renderedImageSize,
  12. required this.originalImageSize,
  13. required this.edgeDetectionResult})
  14. : super(key: key);
  15. final Size renderedImageSize;
  16. final Size originalImageSize;
  17. final EdgeDetectionResult edgeDetectionResult;
  18. @override
  19. State createState() => _EdgeDetectionShapeState();
  20. }
  21. class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
  22. late double edgeDraggerSize;
  23. late EdgeDetectionResult edgeDetectionResult;
  24. late List<Offset> points;
  25. late double renderedImageWidth;
  26. late double renderedImageHeight;
  27. late double top;
  28. late double left;
  29. Offset? currentDragPosition;
  30. @override
  31. void didChangeDependencies() {
  32. double shortestSide = min(
  33. MediaQuery.of(context).size.width, MediaQuery.of(context).size.height);
  34. edgeDraggerSize = shortestSide / 12;
  35. super.didChangeDependencies();
  36. }
  37. @override
  38. void initState() {
  39. edgeDetectionResult = widget.edgeDetectionResult;
  40. _calculateDimensionValues();
  41. super.initState();
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return Magnifier(
  46. visible: currentDragPosition != null,
  47. position: currentDragPosition,
  48. child: Stack(
  49. children: [
  50. _getTouchBubbles(),
  51. CustomPaint(
  52. painter: EdgePainter(
  53. points: points,
  54. color: Theme.of(context)
  55. .colorScheme
  56. .secondary
  57. .withOpacity(0.5)))
  58. ],
  59. ));
  60. }
  61. void _calculateDimensionValues() {
  62. top = 0.0;
  63. left = 0.0;
  64. double widthFactor =
  65. widget.renderedImageSize.width / widget.originalImageSize.width;
  66. double heightFactor =
  67. widget.renderedImageSize.height / widget.originalImageSize.height;
  68. double sizeFactor = min(widthFactor, heightFactor);
  69. renderedImageHeight = widget.originalImageSize.height * sizeFactor;
  70. top = ((widget.renderedImageSize.height - renderedImageHeight) / 2);
  71. renderedImageWidth = widget.originalImageSize.width * sizeFactor;
  72. left = ((widget.renderedImageSize.width - renderedImageWidth) / 2);
  73. }
  74. Offset _getNewPositionAfterDrag(
  75. Offset position, double renderedImageWidth, double renderedImageHeight) {
  76. return Offset(
  77. position.dx / renderedImageWidth, position.dy / renderedImageHeight);
  78. }
  79. Offset _clampOffset(Offset givenOffset) {
  80. double absoluteX = givenOffset.dx * renderedImageWidth;
  81. double absoluteY = givenOffset.dy * renderedImageHeight;
  82. return Offset(absoluteX.clamp(0.0, renderedImageWidth) / renderedImageWidth,
  83. absoluteY.clamp(0.0, renderedImageHeight) / renderedImageHeight);
  84. }
  85. Widget _getTouchBubbles() {
  86. points = [
  87. Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth,
  88. top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
  89. Offset(left + edgeDetectionResult.topRight.dx * renderedImageWidth,
  90. top + edgeDetectionResult.topRight.dy * renderedImageHeight),
  91. Offset(left + edgeDetectionResult.bottomRight.dx * renderedImageWidth,
  92. top + (edgeDetectionResult.bottomRight.dy * renderedImageHeight)),
  93. Offset(left + edgeDetectionResult.bottomLeft.dx * renderedImageWidth,
  94. top + edgeDetectionResult.bottomLeft.dy * renderedImageHeight),
  95. Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth,
  96. top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
  97. ];
  98. onDragFinished() {
  99. currentDragPosition = null;
  100. setState(() {});
  101. }
  102. return SizedBox(
  103. width: widget.renderedImageSize.width,
  104. height: widget.renderedImageSize.height,
  105. child: Stack(
  106. children: [
  107. Positioned(
  108. left: points[0].dx - (edgeDraggerSize / 2),
  109. top: points[0].dy - (edgeDraggerSize / 2),
  110. child: TouchBubble(
  111. size: edgeDraggerSize,
  112. onDrag: (position) {
  113. setState(() {
  114. currentDragPosition = Offset(points[0].dx, points[0].dy);
  115. Offset newTopLeft = _getNewPositionAfterDrag(
  116. position, renderedImageWidth, renderedImageHeight);
  117. edgeDetectionResult.topLeft = _clampOffset(
  118. edgeDetectionResult.topLeft + newTopLeft);
  119. });
  120. },
  121. onDragFinished: onDragFinished)),
  122. Positioned(
  123. left: points[1].dx - (edgeDraggerSize / 2),
  124. top: points[1].dy - (edgeDraggerSize / 2),
  125. child: TouchBubble(
  126. size: edgeDraggerSize,
  127. onDrag: (position) {
  128. setState(() {
  129. Offset newTopRight = _getNewPositionAfterDrag(
  130. position, renderedImageWidth, renderedImageHeight);
  131. edgeDetectionResult.topRight = _clampOffset(
  132. edgeDetectionResult.topRight + newTopRight);
  133. currentDragPosition = Offset(points[1].dx, points[1].dy);
  134. });
  135. },
  136. onDragFinished: onDragFinished)),
  137. Positioned(
  138. left: points[2].dx - (edgeDraggerSize / 2),
  139. top: points[2].dy - (edgeDraggerSize / 2),
  140. child: TouchBubble(
  141. size: edgeDraggerSize,
  142. onDrag: (position) {
  143. setState(() {
  144. Offset newBottomRight = _getNewPositionAfterDrag(
  145. position, renderedImageWidth, renderedImageHeight);
  146. edgeDetectionResult.bottomRight = _clampOffset(
  147. edgeDetectionResult.bottomRight + newBottomRight);
  148. currentDragPosition = Offset(points[2].dx, points[2].dy);
  149. });
  150. },
  151. onDragFinished: onDragFinished)),
  152. Positioned(
  153. left: points[3].dx - (edgeDraggerSize / 2),
  154. top: points[3].dy - (edgeDraggerSize / 2),
  155. child: TouchBubble(
  156. size: edgeDraggerSize,
  157. onDrag: (position) {
  158. setState(() {
  159. Offset newBottomLeft = _getNewPositionAfterDrag(
  160. position, renderedImageWidth, renderedImageHeight);
  161. edgeDetectionResult.bottomLeft = _clampOffset(
  162. edgeDetectionResult.bottomLeft + newBottomLeft);
  163. currentDragPosition = Offset(points[3].dx, points[3].dy);
  164. });
  165. },
  166. onDragFinished: onDragFinished)),
  167. ],
  168. ),
  169. );
  170. }
  171. }