Skip to content

Commit 0577e61

Browse files
Fixed visuals for crop with aspect ratio
1 parent 08486fd commit 0577e61

File tree

7 files changed

+307
-230
lines changed

7 files changed

+307
-230
lines changed

example/lib/main.dart

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MyHomePage extends StatefulWidget {
4141
class _MyHomePageState extends State<MyHomePage> {
4242
late CustomImageCropController controller;
4343
CustomCropShape _currentShape = CustomCropShape.Circle;
44+
CustomImageFit _imageFit = CustomImageFit.fillCropSpace;
4445
final TextEditingController _widthController = TextEditingController();
4546
final TextEditingController _heightController = TextEditingController();
4647
final TextEditingController _radiusController = TextEditingController();
@@ -67,6 +68,12 @@ class _MyHomePageState extends State<MyHomePage> {
6768
});
6869
}
6970

71+
void _changeImageFit(CustomImageFit imageFit) {
72+
setState(() {
73+
_imageFit = imageFit;
74+
});
75+
}
76+
7077
void _updateRatio() {
7178
setState(() {
7279
if (_widthController.text.isNotEmpty) {
@@ -94,76 +101,74 @@ class _MyHomePageState extends State<MyHomePage> {
94101
Expanded(
95102
child: CustomImageCrop(
96103
cropController: controller,
97-
// image: const AssetImage('assets/test.png'), // Any Imageprovider will work, try with a NetworkImage for example...
98-
image: const NetworkImage(
99-
'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'),
104+
image: const AssetImage('assets/test.png'), // Any Imageprovider will work, try with a NetworkImage for example...
105+
// image: const NetworkImage('https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'),
100106
shape: _currentShape,
101-
ratio: _currentShape == CustomCropShape.Ratio
102-
? Ratio(width: _width, height: _height)
103-
: null,
107+
ratio: _currentShape == CustomCropShape.Ratio ? Ratio(width: _width, height: _height) : null,
104108
canRotate: true,
105-
canMove: false,
106-
canScale: false,
107-
borderRadius:
108-
_currentShape == CustomCropShape.Ratio ? _radius : 0,
109+
canMove: true,
110+
canScale: true,
111+
borderRadius: _currentShape == CustomCropShape.Ratio ? _radius : 0,
109112
customProgressIndicator: const CupertinoActivityIndicator(),
110-
// use custom paint if needed
111-
// pathPaint: Paint()
112-
// ..color = Colors.red
113-
// ..strokeWidth = 4.0
114-
// ..style = PaintingStyle.stroke
115-
// ..strokeJoin = StrokeJoin.round,
113+
imageFit: _imageFit,
114+
pathPaint: Paint()
115+
..color = Colors.red
116+
..strokeWidth = 4.0
117+
..style = PaintingStyle.stroke
118+
..strokeJoin = StrokeJoin.round,
116119
),
117120
),
118121
Row(
119122
mainAxisAlignment: MainAxisAlignment.spaceAround,
120123
children: [
121-
IconButton(
122-
icon: const Icon(Icons.refresh), onPressed: controller.reset),
123-
IconButton(
124-
icon: const Icon(Icons.zoom_in),
125-
onPressed: () =>
126-
controller.addTransition(CropImageData(scale: 1.33))),
127-
IconButton(
128-
icon: const Icon(Icons.zoom_out),
129-
onPressed: () =>
130-
controller.addTransition(CropImageData(scale: 0.75))),
131-
IconButton(
132-
icon: const Icon(Icons.rotate_left),
133-
onPressed: () =>
134-
controller.addTransition(CropImageData(angle: -pi / 4))),
135-
IconButton(
136-
icon: const Icon(Icons.rotate_right),
137-
onPressed: () =>
138-
controller.addTransition(CropImageData(angle: pi / 4))),
139-
IconButton(
140-
icon: const Icon(Icons.crop),
141-
onPressed: () async {
142-
final image = await controller.onCropImage();
143-
if (image != null) {
144-
Navigator.of(context).push(MaterialPageRoute(
145-
builder: (BuildContext context) =>
146-
ResultScreen(image: image)));
147-
}
148-
},
149-
),
150-
PopupMenuButton<CustomCropShape>(
124+
IconButton(icon: const Icon(Icons.refresh), onPressed: controller.reset),
125+
IconButton(icon: const Icon(Icons.zoom_in), onPressed: () => controller.addTransition(CropImageData(scale: 1.33))),
126+
IconButton(icon: const Icon(Icons.zoom_out), onPressed: () => controller.addTransition(CropImageData(scale: 0.75))),
127+
IconButton(icon: const Icon(Icons.rotate_left), onPressed: () => controller.addTransition(CropImageData(angle: -pi / 4))),
128+
IconButton(icon: const Icon(Icons.rotate_right), onPressed: () => controller.addTransition(CropImageData(angle: pi / 4))),
129+
PopupMenuButton(
151130
icon: const Icon(Icons.crop_original),
152131
onSelected: _changeCropShape,
153132
itemBuilder: (BuildContext context) {
154133
return CustomCropShape.values.map(
155134
(shape) {
156-
return PopupMenuItem<CustomCropShape>(
135+
return PopupMenuItem(
157136
value: shape,
158137
child: getShapeIcon(shape),
159138
);
160139
},
161140
).toList();
162141
},
163142
),
143+
PopupMenuButton(
144+
icon: const Icon(Icons.fit_screen),
145+
onSelected: _changeImageFit,
146+
itemBuilder: (BuildContext context) {
147+
return CustomImageFit.values.map(
148+
(imageFit) {
149+
return PopupMenuItem(
150+
value: imageFit,
151+
child: Text(imageFit.name),
152+
);
153+
},
154+
).toList();
155+
},
156+
),
157+
IconButton(
158+
icon: const Icon(
159+
Icons.crop,
160+
color: Colors.green,
161+
),
162+
onPressed: () async {
163+
final image = await controller.onCropImage();
164+
if (image != null) {
165+
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => ResultScreen(image: image)));
166+
}
167+
},
168+
),
164169
],
165170
),
166-
if (_currentShape == CustomCropShape.Ratio)
171+
if (_currentShape == CustomCropShape.Ratio) ...[
167172
SizedBox(
168173
child: Row(
169174
children: [
@@ -198,6 +203,7 @@ class _MyHomePageState extends State<MyHomePage> {
198203
],
199204
),
200205
),
206+
],
201207
SizedBox(height: MediaQuery.of(context).padding.bottom),
202208
],
203209
),

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ packages:
4949
path: ".."
5050
relative: true
5151
source: path
52-
version: "0.0.9"
52+
version: "0.0.11"
5353
fake_async:
5454
dependency: transitive
5555
description:
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import 'dart:math';
2+
3+
import 'package:custom_image_crop/src/models/params_model.dart';
4+
import 'package:custom_image_crop/src/widgets/custom_image_crop_widget.dart';
5+
6+
/// Returns params to use for displaying crop screen.
7+
CropFitParams calculateCropFitParams({
8+
required double screenWidth,
9+
required double screenHeight,
10+
required double cropPercentage,
11+
required int imageWidth,
12+
required int imageHeight,
13+
required CustomImageFit imageFit,
14+
required double aspectRatio,
15+
}) {
16+
/// the width of the area to crop
17+
final double cropSizeWidth;
18+
19+
/// the height of the area to crop
20+
final double cropSizeHeight;
21+
22+
/// used to adjust image scale
23+
final double defaultScale;
24+
25+
switch (imageFit) {
26+
case CustomImageFit.fillCropSpace:
27+
if (screenWidth <= screenHeight * aspectRatio) {
28+
cropSizeWidth = screenWidth * cropPercentage;
29+
cropSizeHeight = cropSizeWidth / aspectRatio;
30+
defaultScale = cropSizeWidth / imageWidth;
31+
} else {
32+
cropSizeHeight = screenHeight * cropPercentage;
33+
cropSizeWidth = cropSizeHeight * aspectRatio;
34+
defaultScale = cropSizeHeight / imageHeight;
35+
}
36+
break;
37+
38+
case CustomImageFit.fitCropSpace:
39+
if (screenWidth <= screenHeight * aspectRatio) {
40+
cropSizeWidth = screenWidth * cropPercentage;
41+
cropSizeHeight = cropSizeWidth / aspectRatio;
42+
defaultScale = cropSizeWidth / max(imageWidth, imageHeight * aspectRatio);
43+
} else {
44+
cropSizeHeight = screenHeight * cropPercentage;
45+
cropSizeWidth = cropSizeHeight * aspectRatio;
46+
defaultScale = cropSizeHeight / max(imageHeight, imageWidth / aspectRatio);
47+
}
48+
break;
49+
50+
case CustomImageFit.fillCropWidth:
51+
if (screenWidth <= screenHeight * aspectRatio) {
52+
cropSizeWidth = screenWidth * cropPercentage;
53+
cropSizeHeight = cropSizeWidth / aspectRatio;
54+
} else {
55+
cropSizeHeight = screenHeight * cropPercentage;
56+
cropSizeWidth = cropSizeHeight * aspectRatio;
57+
}
58+
defaultScale = cropSizeWidth / imageWidth;
59+
break;
60+
61+
case CustomImageFit.fillCropHeight:
62+
if (screenWidth <= screenHeight * aspectRatio) {
63+
cropSizeWidth = screenWidth * cropPercentage;
64+
cropSizeHeight = cropSizeWidth / aspectRatio;
65+
} else {
66+
cropSizeHeight = screenHeight * cropPercentage;
67+
cropSizeWidth = cropSizeHeight * aspectRatio;
68+
}
69+
defaultScale = cropSizeHeight / imageHeight;
70+
break;
71+
72+
case CustomImageFit.fitVisibleSpace:
73+
if (screenWidth <= screenHeight * aspectRatio) {
74+
cropSizeWidth = screenWidth * cropPercentage;
75+
cropSizeHeight = cropSizeWidth / aspectRatio;
76+
defaultScale = screenWidth / imageWidth;
77+
} else {
78+
cropSizeHeight = screenHeight * cropPercentage;
79+
cropSizeWidth = cropSizeHeight * aspectRatio;
80+
defaultScale = screenHeight / imageHeight;
81+
}
82+
break;
83+
84+
case CustomImageFit.fillVisibleSpace:
85+
if (screenWidth <= screenHeight * aspectRatio) {
86+
cropSizeWidth = screenWidth * cropPercentage;
87+
cropSizeHeight = cropSizeWidth / aspectRatio;
88+
defaultScale = screenHeight / imageHeight;
89+
} else {
90+
cropSizeHeight = screenHeight * cropPercentage;
91+
cropSizeWidth = cropSizeHeight * aspectRatio;
92+
defaultScale = screenWidth / imageWidth;
93+
}
94+
break;
95+
96+
case CustomImageFit.fillVisibleHeight:
97+
if (screenWidth <= screenHeight * aspectRatio) {
98+
cropSizeWidth = screenWidth * cropPercentage;
99+
cropSizeHeight = cropSizeWidth / aspectRatio;
100+
} else {
101+
cropSizeHeight = screenHeight * cropPercentage;
102+
cropSizeWidth = cropSizeHeight * aspectRatio;
103+
}
104+
defaultScale = screenHeight / imageHeight;
105+
break;
106+
107+
case CustomImageFit.fillVisiblelWidth:
108+
if (screenWidth <= screenHeight * aspectRatio) {
109+
cropSizeWidth = screenWidth * cropPercentage;
110+
cropSizeHeight = cropSizeWidth / aspectRatio;
111+
} else {
112+
cropSizeHeight = screenHeight * cropPercentage;
113+
cropSizeWidth = cropSizeHeight * aspectRatio;
114+
}
115+
defaultScale = screenWidth / imageWidth;
116+
break;
117+
}
118+
119+
return CropFitParams(
120+
cropSizeWidth: cropSizeWidth,
121+
cropSizeHeight: cropSizeHeight,
122+
additionalScale: defaultScale,
123+
);
124+
}

lib/src/calculators/calculate_crop_params.dart

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)