Skip to content

Commit

Permalink
new: rotateCropArea parameter in CropGridViewer
Browse files Browse the repository at this point in the history
  • Loading branch information
LeGoffMael committed Jan 3, 2023
1 parent 649d161 commit ae66407
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ This widget is used to enable the crop actions on top of the video (CropGridView
| -------------------------------- | --------------------------------- |
| required VideoEditorController controller | The `controller` param is mandatory so every change in the controller settings will propagate in the crop view |
| EdgeInsets margin | The amount of space by which to inset the crop view, not used in preview mode |
| bool rotateCropArea | To preserve `preferredCropAspectRatio` when crop view is rotated |

#### Trimmer

Expand Down
1 change: 1 addition & 0 deletions example/lib/crop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class CropScreen extends StatelessWidget {
Expanded(
child: CropGridViewer.edit(
controller: controller,
rotateCropArea: false,
margin: const EdgeInsets.symmetric(horizontal: 20),
),
),
Expand Down
37 changes: 26 additions & 11 deletions lib/ui/crop/crop_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ class CropGridViewer extends StatefulWidget {
super.key,
required this.controller,
}) : showGrid = false,
rotateCropArea = true,
margin = EdgeInsets.zero;

const CropGridViewer.edit({
super.key,
required this.controller,
this.margin = const EdgeInsets.symmetric(horizontal: 20),
this.rotateCropArea = true,
}) : showGrid = true;

/// The [controller] param is mandatory so every change in the controller settings will propagate in the crop view
Expand All @@ -47,6 +49,13 @@ class CropGridViewer extends StatefulWidget {
/// so in case of a change the new layout can be computed properly (i.e after a rotation)
final EdgeInsets margin;

/// The [rotateCropArea] parameters specifies if the crop should be rotated along
/// with the video
/// Set it to `false` to preserve `_controller.preferredAspectRatio` on rotation
///
/// Defaults to `true` (like iOS Photos app crop)
final bool rotateCropArea;

@override
State<CropGridViewer> createState() => _CropGridViewerState();
}
Expand All @@ -60,7 +69,6 @@ class _CropGridViewerState extends State<CropGridViewer> {
Size _layout = Size.zero;
CropBoundaries _boundary = CropBoundaries.none;

double? _preferredCropAspectRatio;
late VideoEditorController _controller;

/// Minimum size of the cropped area
Expand Down Expand Up @@ -92,6 +100,13 @@ class _CropGridViewerState extends State<CropGridViewer> {
super.dispose();
}

/// Returns the proper aspect ratio to apply depending on view rotation
double? get aspectRatio => widget.rotateCropArea == false &&
_controller.isRotated &&
_controller.preferredCropAspectRatio != null
? getOppositeRatio(_controller.preferredCropAspectRatio!)
: _controller.preferredCropAspectRatio;

/// Returns the size of the max crop dimension based on available space and
/// original video aspect ratio
Size computeLayout() {
Expand All @@ -114,20 +129,20 @@ class _CropGridViewerState extends State<CropGridViewer> {

/// Compute new [Rect] crop area depending of [_controller] data and layout size
void _calculatePreferedCrop() {
_preferredCropAspectRatio = _controller.preferredCropAspectRatio;

// set cached crop values to adjust it later
Rect newRect = calculateCroppedRect(
_controller,
_layout,
min: _controller.cacheMinCrop,
max: _controller.cacheMaxCrop,
);
if (_preferredCropAspectRatio != null) {
if (_controller.preferredCropAspectRatio != null) {
newRect = resizeCropToRatio(
_layout,
newRect,
_preferredCropAspectRatio!,
widget.rotateCropArea == false && _controller.isRotated
? getOppositeRatio(_controller.preferredCropAspectRatio!)
: _controller.preferredCropAspectRatio!,
);
}

Expand Down Expand Up @@ -277,19 +292,19 @@ class _CropGridViewerState extends State<CropGridViewer> {
bottom = min(_layout.height, bottom ?? _rect.value.bottom);

// update crop height or width to adjust to the selected aspect ratio
if (_preferredCropAspectRatio != null) {
if (aspectRatio != null) {
final width = right - left;
final height = bottom - top;

if (width / height > _preferredCropAspectRatio!) {
if (width / height > aspectRatio!) {
switch (_boundary) {
case CropBoundaries.topLeft:
case CropBoundaries.bottomLeft:
left = right - height * _preferredCropAspectRatio!;
left = right - height * aspectRatio!;
break;
case CropBoundaries.topRight:
case CropBoundaries.bottomRight:
right = left + height * _preferredCropAspectRatio!;
right = left + height * aspectRatio!;
break;
default:
assert(false);
Expand All @@ -298,11 +313,11 @@ class _CropGridViewerState extends State<CropGridViewer> {
switch (_boundary) {
case CropBoundaries.topLeft:
case CropBoundaries.topRight:
top = bottom - width / _preferredCropAspectRatio!;
top = bottom - width / aspectRatio!;
break;
case CropBoundaries.bottomLeft:
case CropBoundaries.bottomRight:
bottom = top + width / _preferredCropAspectRatio!;
bottom = top + width / aspectRatio!;
break;
default:
assert(false);
Expand Down

0 comments on commit ae66407

Please sign in to comment.