From d88edbeaa9363145ded6bcc250a2c5d6eab1c647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20G=C3=B3rski?= Date: Tue, 16 Nov 2021 13:17:28 +0100 Subject: [PATCH 1/3] Bugfix Precropping issue _reCenterImage function now takes into account child widget aspect ratio when calculating boundaries for offset clamping. --- lib/src/crop.dart | 84 +++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 57 deletions(-) diff --git a/lib/src/crop.dart b/lib/src/crop.dart index 3f2dc0f..bd05a80 100644 --- a/lib/src/crop.dart +++ b/lib/src/crop.dart @@ -69,6 +69,7 @@ class _CropState extends State with TickerProviderStateMixin { final _key = GlobalKey(); final _parent = GlobalKey(); final _repaintBoundaryKey = GlobalKey(); + final _childKey = GlobalKey(); double _previousScale = 1; Offset _previousOffset = Offset.zero; @@ -114,66 +115,35 @@ class _CropState extends State with TickerProviderStateMixin { } void _reCenterImage([bool animate = true]) { - //final totalSize = _parent.currentContext.size; - final sz = _key.currentContext!.size!; final s = widget.controller._scale * widget.controller._getMinScale(); - final w = sz.width; - final h = sz.height; - final offset = _toVector2(widget.controller._offset); - final canvas = Rectangle.fromLTWH(0, 0, w, h); - final obb = Obb2( - center: offset + canvas.center, - width: w * s, - height: h * s, - rotation: widget.controller._rotation, - ); - - final bakedObb = obb.bake(); + final childWidgetSize = + (_childKey.currentContext?.findRenderObject() as RenderBox).size; + final w = (sz.width * (childWidgetSize.aspectRatio / sz.aspectRatio)) + .truncateToDouble(); + final h = sz.height.truncateToDouble(); + + final canvas = Rect.fromLTWH(0, 0, w, h); + final imageBoundaries = Rect.fromCenter( + center: widget.controller._offset + canvas.center, + width: w * s * cos(vm.radians(widget.controller._rotation)).abs() + + h * s * sin(vm.radians(widget.controller._rotation)).abs(), + height: w * s * sin(vm.radians(widget.controller._rotation)).abs() + + h * s * cos(vm.radians(widget.controller._rotation)).abs()); + + var clampBoundaries = Rect.fromCenter( + center: Offset.zero, + width: ((imageBoundaries.width - sz.width).abs().floorToDouble()), + height: (imageBoundaries.height - sz.height).abs().floorToDouble()); + + final clampedOffset = Offset( + min(max(widget.controller._offset.dx, clampBoundaries.left), + clampBoundaries.right.floorToDouble()), + min(max(widget.controller._offset.dy, clampBoundaries.top), + clampBoundaries.bottom)); _startOffset = widget.controller._offset; - _endOffset = widget.controller._offset; - - final ctl = canvas.topLeft; - final ctr = canvas.topRight; - final cbr = canvas.bottomRight; - final cbl = canvas.bottomLeft; - - final ll = Line(bakedObb.topLeft, bakedObb.bottomLeft); - final tt = Line(bakedObb.topRight, bakedObb.topLeft); - final rr = Line(bakedObb.bottomRight, bakedObb.topRight); - final bb = Line(bakedObb.bottomLeft, bakedObb.bottomRight); - - final tl = ll.project(ctl); - final tr = tt.project(ctr); - final br = rr.project(cbr); - final bl = bb.project(cbl); - - final dtl = ll.distanceToPoint(ctl); - final dtr = tt.distanceToPoint(ctr); - final dbr = rr.distanceToPoint(cbr); - final dbl = bb.distanceToPoint(cbl); - - if (dtl > 0) { - final d = _toOffset(ctl - tl); - _endOffset += d; - } - - if (dtr > 0) { - final d = _toOffset(ctr - tr); - _endOffset += d; - } - - if (dbr > 0) { - final d = _toOffset(cbr - br); - _endOffset += d; - } - if (dbl > 0) { - final d = _toOffset(cbl - bl); - _endOffset += d; - } - - widget.controller._offset = _endOffset; + widget.controller._offset = _endOffset = clampedOffset; if (animate) { if (_controller.isCompleted || _controller.isAnimating) { @@ -255,7 +225,7 @@ class _CropState extends State with TickerProviderStateMixin { ..rotateZ(r) ..scale(s, s, 1), child: FittedBox( - child: widget.child, + child: Container(key: _childKey, child: widget.child), fit: BoxFit.cover, ), ), From c0ae7b09d679ee417994f9c454586387956d7ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20G=C3=B3rski?= Date: Tue, 16 Nov 2021 14:13:11 +0100 Subject: [PATCH 2/3] Fixing recenter for vertical images Rescaling of dimensions needs to be done depending of image orientation. Previous implementation works correct only for horizontal images. --- lib/src/crop.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/src/crop.dart b/lib/src/crop.dart index bd05a80..9865ca0 100644 --- a/lib/src/crop.dart +++ b/lib/src/crop.dart @@ -119,9 +119,18 @@ class _CropState extends State with TickerProviderStateMixin { final s = widget.controller._scale * widget.controller._getMinScale(); final childWidgetSize = (_childKey.currentContext?.findRenderObject() as RenderBox).size; - final w = (sz.width * (childWidgetSize.aspectRatio / sz.aspectRatio)) - .truncateToDouble(); - final h = sz.height.truncateToDouble(); + + double w, h; + final ratio = childWidgetSize.aspectRatio / sz.aspectRatio; + if (childWidgetSize.aspectRatio < 1.0) { + // Vertical image. Height needs to be rescaled according to ratio. + w = sz.width.truncateToDouble(); + h = (sz.height / ratio).truncateToDouble(); + } else { + // Horizontal or square image. Width needs to be rescaled according to ratio (for square ratio is 1.0). + w = (sz.width * ratio).truncateToDouble(); + h = sz.height.truncateToDouble(); + } final canvas = Rect.fromLTWH(0, 0, w, h); final imageBoundaries = Rect.fromCenter( From 720642410ae4bbb53e3a035be0de180be0880597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20G=C3=B3rski?= Date: Wed, 17 Nov 2021 07:23:44 +0100 Subject: [PATCH 3/3] After review changes --- lib/src/crop.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/src/crop.dart b/lib/src/crop.dart index 9865ca0..ecdc844 100644 --- a/lib/src/crop.dart +++ b/lib/src/crop.dart @@ -124,12 +124,12 @@ class _CropState extends State with TickerProviderStateMixin { final ratio = childWidgetSize.aspectRatio / sz.aspectRatio; if (childWidgetSize.aspectRatio < 1.0) { // Vertical image. Height needs to be rescaled according to ratio. - w = sz.width.truncateToDouble(); - h = (sz.height / ratio).truncateToDouble(); + w = sz.width; + h = sz.height / ratio; } else { // Horizontal or square image. Width needs to be rescaled according to ratio (for square ratio is 1.0). - w = (sz.width * ratio).truncateToDouble(); - h = sz.height.truncateToDouble(); + w = sz.width * ratio; + h = sz.height; } final canvas = Rect.fromLTWH(0, 0, w, h); @@ -146,10 +146,10 @@ class _CropState extends State with TickerProviderStateMixin { height: (imageBoundaries.height - sz.height).abs().floorToDouble()); final clampedOffset = Offset( - min(max(widget.controller._offset.dx, clampBoundaries.left), - clampBoundaries.right.floorToDouble()), - min(max(widget.controller._offset.dy, clampBoundaries.top), - clampBoundaries.bottom)); + widget.controller._offset.dx + .clamp(clampBoundaries.left, clampBoundaries.right), + widget.controller._offset.dy + .clamp(clampBoundaries.top, clampBoundaries.bottom)); _startOffset = widget.controller._offset; widget.controller._offset = _endOffset = clampedOffset;