Skip to content

Commit 93ea9f5

Browse files
Version bump + Formatting
1 parent bc8905d commit 93ea9f5

File tree

3 files changed

+73
-32
lines changed

3 files changed

+73
-32
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## [0.0.14] - 2024-12-30
2+
3+
- Added maskShape so you can crop using a different mask than for visualisation (e.g. circle mask for visualisation, but square mask for cropping)
4+
- Fixed issue with aspectratio < 1 resulting in a to big cropSizeHeight
5+
16
## [0.0.13] - 2023-10-26
27

38
- Added forceInsideCropArea, whether image area must cover clip path. Default is false

lib/src/widgets/custom_image_crop_widget.dart

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ class CustomImageCrop extends StatefulWidget {
141141
Paint? imagePaintDuringCrop,
142142
this.forceInsideCropArea = false,
143143
Key? key,
144-
}) : this.imagePaintDuringCrop = imagePaintDuringCrop ?? (Paint()..filterQuality = FilterQuality.high),
144+
}) : this.imagePaintDuringCrop = imagePaintDuringCrop ??
145+
(Paint()..filterQuality = FilterQuality.high),
145146
assert(
146147
!(shape == CustomCropShape.Ratio && ratio == null),
147148
"If shape is set to Ratio, ratio should not be null.",
@@ -152,7 +153,8 @@ class CustomImageCrop extends StatefulWidget {
152153
_CustomImageCropState createState() => _CustomImageCropState();
153154
}
154155

155-
class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropListener {
156+
class _CustomImageCropState extends State<CustomImageCrop>
157+
with CustomImageCropListener {
156158
CropImageData? _dataTransitionStart;
157159
late Path _path;
158160
late Path _maskPath;
@@ -263,7 +265,8 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
263265
left: data.x + _width / 2,
264266
top: data.y + _height / 2,
265267
child: Transform(
266-
transform: Matrix4.diagonal3(vector_math.Vector3(scale, scale, scale))
268+
transform: Matrix4.diagonal3(
269+
vector_math.Vector3(scale, scale, scale))
267270
..rotateZ(data.angle)
268271
..translate(-image.width / 2, -image.height / 2),
269272
child: Image(
@@ -293,7 +296,8 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
293296
}
294297

295298
void onScaleUpdate(ScaleEvent event) {
296-
final scale = widget.canScale ? event.scale : (_dataTransitionStart?.scale ?? 1.0);
299+
final scale =
300+
widget.canScale ? event.scale : (_dataTransitionStart?.scale ?? 1.0);
297301

298302
final angle = widget.canRotate ? event.rotationAngle : 0.0;
299303

@@ -319,7 +323,8 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
319323
void onMoveUpdate(MoveEvent event) {
320324
if (!widget.canMove) return;
321325

322-
widget.cropController.addTransition(CropImageData(x: event.delta.dx, y: event.delta.dy));
326+
widget.cropController
327+
.addTransition(CropImageData(x: event.delta.dx, y: event.delta.dy));
323328
}
324329

325330
Rect _getInitialImageRect() {
@@ -335,7 +340,8 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
335340
aspectRatio: (widget.ratio?.width ?? 1) / (widget.ratio?.height ?? 1),
336341
);
337342
final initialWidth = _imageAsUIImage!.width * cropFitParams.additionalScale;
338-
final initialHeight = _imageAsUIImage!.height * cropFitParams.additionalScale;
343+
final initialHeight =
344+
_imageAsUIImage!.height * cropFitParams.additionalScale;
339345
return Rect.fromLTWH(
340346
(_width - initialWidth) / 2,
341347
(_height - initialHeight) / 2,
@@ -363,38 +369,53 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
363369

364370
if (transition.x != 0 || transition.y != 0) {
365371
if (isRotated) {
366-
_addTransitionInternal(CropImageData(x: startX - data.x, y: startY - data.y));
372+
_addTransitionInternal(
373+
CropImageData(x: startX - data.x, y: startY - data.y));
367374
} else {
368375
final imageRect = _getImageRect(initialImageRect, data.scale);
369376
double deltaX = min(pathRect.left - imageRect.left, 0);
370-
deltaX = pathRect.right > imageRect.right ? pathRect.right - imageRect.right : deltaX;
377+
deltaX = pathRect.right > imageRect.right
378+
? pathRect.right - imageRect.right
379+
: deltaX;
371380
double deltaY = min(pathRect.top - imageRect.top, 0);
372-
deltaY = pathRect.bottom > imageRect.bottom ? pathRect.bottom - imageRect.bottom : deltaY;
381+
deltaY = pathRect.bottom > imageRect.bottom
382+
? pathRect.bottom - imageRect.bottom
383+
: deltaY;
373384
_addTransitionInternal(CropImageData(x: deltaX, y: deltaY));
374385
}
375386
return;
376387
}
377-
double minEdgeHalf = min(initialImageRect.width, initialImageRect.height) / 2;
378-
double adaptScale = _calculateScaleAfterRotate(pathRect, data.scale, initialImageRect, minEdgeHalf);
388+
double minEdgeHalf =
389+
min(initialImageRect.width, initialImageRect.height) / 2;
390+
double adaptScale = _calculateScaleAfterRotate(
391+
pathRect, data.scale, initialImageRect, minEdgeHalf);
379392
_addTransitionInternal(CropImageData(scale: adaptScale / data.scale));
380393
}
381394

382395
Rect _getImageRect(Rect initialImageRect, double currentScale) {
383396
final diffScale = (1 - currentScale) / 2;
384-
final left = initialImageRect.left + diffScale * initialImageRect.width + data.x;
385-
final top = initialImageRect.top + diffScale * initialImageRect.height + data.y;
386-
Rect imageRect = Rect.fromLTWH(left, top, currentScale * initialImageRect.width, currentScale * initialImageRect.height);
397+
final left =
398+
initialImageRect.left + diffScale * initialImageRect.width + data.x;
399+
final top =
400+
initialImageRect.top + diffScale * initialImageRect.height + data.y;
401+
Rect imageRect = Rect.fromLTWH(
402+
left,
403+
top,
404+
currentScale * initialImageRect.width,
405+
currentScale * initialImageRect.height);
387406
return imageRect;
388407
}
389408

390-
double _getDistanceBetweenPointAndLine(Offset point, Offset lineStart, Offset lineEnd) {
409+
double _getDistanceBetweenPointAndLine(
410+
Offset point, Offset lineStart, Offset lineEnd) {
391411
if (lineEnd.dy == lineStart.dy) {
392412
return (point.dy - lineStart.dy).abs();
393413
}
394414
if (lineEnd.dx == lineStart.dx) {
395415
return (point.dx - lineStart.dx).abs();
396416
}
397-
double line1Slop = (lineEnd.dy - lineStart.dy) / (lineEnd.dx - lineStart.dx);
417+
double line1Slop =
418+
(lineEnd.dy - lineStart.dy) / (lineEnd.dx - lineStart.dx);
398419
double line1Delta = lineEnd.dy - lineEnd.dx * line1Slop;
399420
double line2Slop = -1 / line1Slop;
400421
double line2Delta = point.dy - point.dx * line2Slop;
@@ -403,11 +424,13 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
403424
return (Offset(crossPointX, crossPointY) - point).distance;
404425
}
405426

406-
bool _isContainPath(Rect initialImageRect, Rect pathRect, double currentScale) {
427+
bool _isContainPath(
428+
Rect initialImageRect, Rect pathRect, double currentScale) {
407429
final imageRect = _getImageRect(initialImageRect, currentScale);
408430
Offset topLeft, topRight, bottomLeft, bottomRight;
409431
final rad = atan(imageRect.height / imageRect.width);
410-
final len = sqrt(pow(imageRect.width / 2, 2) + pow(imageRect.height / 2, 2));
432+
final len =
433+
sqrt(pow(imageRect.width / 2, 2) + pow(imageRect.height / 2, 2));
411434
bool isRotated = data.angle != 0;
412435

413436
if (isRotated) {
@@ -418,9 +441,11 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
418441
final cosCounterClockValue = len * cos(counterClockAngle);
419442
final sinCounterClockValue = len * sin(counterClockAngle);
420443
bottomRight = imageRect.center.translate(cosClockValue, sinClockValue);
421-
topRight = imageRect.center.translate(cosCounterClockValue, -sinCounterClockValue);
444+
topRight = imageRect.center
445+
.translate(cosCounterClockValue, -sinCounterClockValue);
422446
topLeft = imageRect.center.translate(-cosClockValue, -sinClockValue);
423-
bottomLeft = imageRect.center.translate(-cosCounterClockValue, sinCounterClockValue);
447+
bottomLeft = imageRect.center
448+
.translate(-cosCounterClockValue, sinCounterClockValue);
424449
} else {
425450
bottomRight = imageRect.bottomRight;
426451
topRight = imageRect.topRight;
@@ -431,10 +456,15 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
431456
if (widget.shape == CustomCropShape.Circle) {
432457
final anchor = max(pathRect.width, pathRect.height) / 2;
433458
final pathCenter = pathRect.center;
434-
return _getDistanceBetweenPointAndLine(pathCenter, topLeft, topRight) >= anchor &&
435-
_getDistanceBetweenPointAndLine(pathCenter, topRight, bottomRight) >= anchor &&
436-
_getDistanceBetweenPointAndLine(pathCenter, bottomLeft, bottomRight) >= anchor &&
437-
_getDistanceBetweenPointAndLine(pathCenter, topLeft, bottomLeft) >= anchor;
459+
return _getDistanceBetweenPointAndLine(pathCenter, topLeft, topRight) >=
460+
anchor &&
461+
_getDistanceBetweenPointAndLine(pathCenter, topRight, bottomRight) >=
462+
anchor &&
463+
_getDistanceBetweenPointAndLine(
464+
pathCenter, bottomLeft, bottomRight) >=
465+
anchor &&
466+
_getDistanceBetweenPointAndLine(pathCenter, topLeft, bottomLeft) >=
467+
anchor;
438468
}
439469

440470
if (isRotated) {
@@ -444,19 +474,28 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
444474
..lineTo(bottomRight.dx, bottomRight.dy)
445475
..lineTo(bottomLeft.dx, bottomLeft.dy)
446476
..close();
447-
return imagePath.contains(pathRect.topLeft) && imagePath.contains(pathRect.topRight) && imagePath.contains(pathRect.bottomLeft) && imagePath.contains(pathRect.bottomRight);
477+
return imagePath.contains(pathRect.topLeft) &&
478+
imagePath.contains(pathRect.topRight) &&
479+
imagePath.contains(pathRect.bottomLeft) &&
480+
imagePath.contains(pathRect.bottomRight);
448481
} else {
449-
return imageRect.contains(pathRect.topLeft) && imageRect.contains(pathRect.topRight) && imageRect.contains(pathRect.bottomLeft) && imageRect.contains(pathRect.bottomRight);
482+
return imageRect.contains(pathRect.topLeft) &&
483+
imageRect.contains(pathRect.topRight) &&
484+
imageRect.contains(pathRect.bottomLeft) &&
485+
imageRect.contains(pathRect.bottomRight);
450486
}
451487
}
452488

453-
double _calculateScaleAfterRotate(Rect pathRect, double startScale, Rect initialImageRect, double minEdgeHalf) {
489+
double _calculateScaleAfterRotate(Rect pathRect, double startScale,
490+
Rect initialImageRect, double minEdgeHalf) {
454491
final imageCenter = initialImageRect.center.translate(data.x, data.y);
455492
final topLeftDistance = (pathRect.topLeft - imageCenter).distance;
456493
final topRightDistance = (pathRect.topRight - imageCenter).distance;
457494
final bottomLeftDistance = (pathRect.bottomLeft - imageCenter).distance;
458495
final bottomRightDistance = (pathRect.bottomRight - imageCenter).distance;
459-
final maxDistance = max(max(max(topLeftDistance, topRightDistance), bottomLeftDistance), bottomRightDistance);
496+
final maxDistance = max(
497+
max(max(topLeftDistance, topRightDistance), bottomLeftDistance),
498+
bottomRightDistance);
460499
double endScale = maxDistance / minEdgeHalf;
461500

462501
if (startScale >= endScale) {

pubspec.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: custom_image_crop
22
description: An image cropper that is customizable. You can rotate, scale and translate either through gestures or a controller
3-
version: 0.0.13
3+
version: 0.0.14
44
homepage: https://github.com/icapps/flutter-custom-image-crop
55

66
environment:
@@ -16,6 +16,3 @@ dependencies:
1616
dev_dependencies:
1717
flutter_test:
1818
sdk: flutter
19-
20-
flutter:
21-

0 commit comments

Comments
 (0)