@@ -2,6 +2,7 @@ import 'dart:async';
2
2
import 'dart:math' ;
3
3
import 'dart:ui' as ui;
4
4
5
+ import 'package:custom_image_crop/src/models/params_model.dart' ;
5
6
import 'package:flutter/material.dart' ;
6
7
import 'package:gesture_x_detector/gesture_x_detector.dart' ;
7
8
import 'package:vector_math/vector_math_64.dart' as vector_math;
@@ -10,6 +11,8 @@ import 'package:custom_image_crop/src/controllers/controller.dart';
10
11
import 'package:custom_image_crop/src/painters/dotted_path_painter.dart' ;
11
12
import 'package:custom_image_crop/src/clippers/inverted_clipper.dart' ;
12
13
import 'package:custom_image_crop/src/models/model.dart' ;
14
+ part 'package:custom_image_crop/src/calculators/calculate_crop_params.dart' ;
15
+ part 'package:custom_image_crop/src/calculators/calculate_on_crop_params.dart' ;
13
16
14
17
/// An image cropper that is customizable.
15
18
/// You can rotate, scale and translate either
@@ -31,6 +34,9 @@ class CustomImageCrop extends StatefulWidget {
31
34
/// The shape of the cropping area
32
35
final CustomCropShape shape;
33
36
37
+ /// How to fit image inside visible space
38
+ final CustomImageFit imageFit;
39
+
34
40
/// The percentage of the available area that is
35
41
/// reserved for the cropping area
36
42
final double cropPercentage;
@@ -83,6 +89,7 @@ class CustomImageCrop extends StatefulWidget {
83
89
this .overlayColor = const Color .fromRGBO (0 , 0 , 0 , 0.5 ),
84
90
this .backgroundColor = Colors .white,
85
91
this .shape = CustomCropShape .Circle ,
92
+ this .imageFit = CustomImageFit .fitCropSpace,
86
93
this .cropPercentage = 0.8 ,
87
94
this .drawPath = DottedCropPathPainter .drawPath,
88
95
this .canRotate = true ,
@@ -159,10 +166,16 @@ class _CustomImageCropState extends State<CustomImageCrop>
159
166
builder: (context, constraints) {
160
167
_width = constraints.maxWidth;
161
168
_height = constraints.maxHeight;
162
- final cropWidth = min (_width, _height) * widget.cropPercentage;
163
- final defaultScale = cropWidth / max (image.width, image.height);
164
- final scale = data.scale * defaultScale;
165
- _path = _getPath (cropWidth, _width, _height);
169
+ final cropParams = calculateCropParams (
170
+ cropPercentage: widget.cropPercentage,
171
+ imageFit: widget.imageFit,
172
+ imageHeight: image.height,
173
+ imageWidth: image.width,
174
+ screenHeight: _height,
175
+ screenWidth: _width,
176
+ );
177
+ final scale = data.scale * cropParams.additionalScale;
178
+ _path = _getPath (cropParams.cropSizeToPaint, _width, _height);
166
179
return XGestureDetector (
167
180
onMoveStart: onMoveStart,
168
181
onMoveUpdate: onMoveUpdate,
@@ -270,20 +283,26 @@ class _CustomImageCropState extends State<CustomImageCrop>
270
283
final imageHeight = _imageAsUIImage! .height;
271
284
final pictureRecorder = ui.PictureRecorder ();
272
285
final canvas = Canvas (pictureRecorder);
273
- final uiWidth = min (_width, _height) * widget.cropPercentage;
274
- final cropWidth = max (imageWidth, imageHeight).toDouble ();
275
- final translateScale = cropWidth / uiWidth;
276
- final scale = data.scale;
277
- final clipPath = Path .from (_getPath (cropWidth, cropWidth, cropWidth));
286
+ final onCropParams = caclulateOnCropParams (
287
+ cropPercentage: widget.cropPercentage,
288
+ imageFit: widget.imageFit,
289
+ imageHeight: imageHeight,
290
+ imageWidth: imageWidth,
291
+ screenHeight: _height,
292
+ screenWidth: _width,
293
+ dataScale: data.scale,
294
+ );
295
+ final clipPath =
296
+ Path .from (_getPath (onCropParams.cropSize, onCropParams.cropSize, onCropParams.cropSize));
278
297
final matrix4Image = Matrix4 .diagonal3 (vector_math.Vector3 .all (1 ))
279
- ..translate (translateScale * data.x + cropWidth / 2 ,
280
- translateScale * data.y + cropWidth / 2 )
281
- ..scale (scale)
298
+ ..translate (onCropParams. translateScale * data.x + onCropParams.cropSize / 2 ,
299
+ onCropParams. translateScale * data.y + onCropParams.cropSize / 2 )
300
+ ..scale (onCropParams. scale)
282
301
..rotateZ (data.angle);
283
302
final bgPaint = Paint ()
284
303
..color = widget.backgroundColor
285
304
..style = PaintingStyle .fill;
286
- canvas.drawRect (Rect .fromLTWH (0 , 0 , cropWidth, cropWidth ), bgPaint);
305
+ canvas.drawRect (Rect .fromLTWH (0 , 0 , onCropParams.cropSize, onCropParams.cropSize ), bgPaint);
287
306
canvas.save ();
288
307
canvas.clipPath (clipPath);
289
308
canvas.transform (matrix4Image.storage);
@@ -298,7 +317,7 @@ class _CustomImageCropState extends State<CustomImageCrop>
298
317
299
318
ui.Picture picture = pictureRecorder.endRecording ();
300
319
ui.Image image =
301
- await picture.toImage (cropWidth. floor (), cropWidth .floor ());
320
+ await picture.toImage (onCropParams.cropSize. floor (), onCropParams.cropSize .floor ());
302
321
303
322
// Adding compute would be preferrable. Unfortunately we cannot pass an ui image to this.
304
323
// A workaround would be to save the image and load it inside of the isolate
@@ -333,3 +352,13 @@ enum CustomCropShape {
333
352
Circle ,
334
353
Square ,
335
354
}
355
+
356
+ enum CustomImageFit {
357
+ fitCropSpace,
358
+ fillCropWidth,
359
+ fillCropHeight,
360
+ fitVisibleSpace,
361
+ fillVisibleSpace,
362
+ fillVisibleHeight,
363
+ fillVisiblelWidth,
364
+ }
0 commit comments