editor: dynamic padding
This commit is contained in:
parent
8fe267d345
commit
5c297c1daf
2 changed files with 48 additions and 8 deletions
|
@ -90,7 +90,7 @@ class _CropperState extends State<Cropper> with SingleTickerProviderStateMixin {
|
|||
|
||||
void _registerWidget(Cropper widget) {
|
||||
_subscriptions.add(widget.magnifierController.stateStream.listen(_onViewStateChanged));
|
||||
_subscriptions.add(widget.magnifierController.scaleBoundariesStream.map((v) => v.viewportSize).listen(_onViewportSizeChanged));
|
||||
_subscriptions.add(widget.magnifierController.scaleBoundariesStream.map((v) => v.viewportSize).distinct().listen(_onViewportSizeChanged));
|
||||
_subscriptions.add(widget.transformController.activityStream.listen(_onTransformActivity));
|
||||
_subscriptions.add(widget.transformController.transformationStream.map((v) => v.orientation).distinct().listen(_onOrientationChanged));
|
||||
_subscriptions.add(widget.transformController.transformationStream.map((v) => v.straightenDegrees).distinct().listen(_onStraightenDegreesChanged));
|
||||
|
@ -454,13 +454,41 @@ class _CropperState extends State<Cropper> with SingleTickerProviderStateMixin {
|
|||
if (boundaries != null) {
|
||||
magnifierController.setScaleBoundaries(
|
||||
boundaries.copyWith(
|
||||
padding: const EdgeInsets.all(double.infinity),
|
||||
padding: _getBoundariesPadding,
|
||||
),
|
||||
);
|
||||
}
|
||||
_showRegion();
|
||||
}
|
||||
|
||||
EdgeInsets _getBoundariesPadding(double scale) {
|
||||
// TODO TLAD handle orientation
|
||||
if (transformation.orientation != TransformOrientation.normal) {
|
||||
return const EdgeInsets.all(double.infinity);
|
||||
}
|
||||
// TODO TLAD handle straightening
|
||||
if (transformation.straightenDegrees != 0) {
|
||||
return const EdgeInsets.all(double.infinity);
|
||||
}
|
||||
|
||||
final viewState = _getViewState();
|
||||
if (viewState != null) {
|
||||
final viewportSize = viewState.viewportSize;
|
||||
final contentSize = viewState.contentSize;
|
||||
if (viewportSize != null && contentSize != null) {
|
||||
final fullRegion = CropRegion.fromRect(Offset.zero & contentSize);
|
||||
final fullOutline = _containingOutlineFromRegion(viewState, fullRegion);
|
||||
final cropOutline = _outlineNotifier.value;
|
||||
|
||||
final paddingWidth = max(0.0, (min(fullOutline.width, viewportSize.width) - cropOutline.width) / 2);
|
||||
final paddingHeight = max(0.0, (min(fullOutline.height, viewportSize.height) - cropOutline.height) / 2);
|
||||
return EdgeInsets.symmetric(vertical: paddingHeight, horizontal: paddingWidth);
|
||||
}
|
||||
}
|
||||
|
||||
return EdgeInsets.zero;
|
||||
}
|
||||
|
||||
ViewState? _getViewState() {
|
||||
final scaleBoundaries = magnifierController.scaleBoundaries;
|
||||
if (scaleBoundaries == null) return null;
|
||||
|
@ -560,6 +588,16 @@ class _CropperState extends State<Cropper> with SingleTickerProviderStateMixin {
|
|||
return clampedRegion;
|
||||
}
|
||||
|
||||
Rect _containingOutlineFromRegion(ViewState viewState, CropRegion region) {
|
||||
final regionToOutlineMatrix = _getRegionToOutlineMatrix(viewState);
|
||||
final points = region.corners.map(regionToOutlineMatrix.transformOffset).toList();
|
||||
final dxSet = points.map((v) => v.dx).toSet();
|
||||
final dySet = points.map((v) => v.dy).toSet();
|
||||
final topLeft = Offset(dxSet.reduce(min), dySet.reduce(min));
|
||||
final bottomRight = Offset(dxSet.reduce(max), dySet.reduce(max));
|
||||
return Rect.fromPoints(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
Rect _containedOutlineFromRegion(ViewState viewState, CropRegion region) {
|
||||
final regionToOutlineMatrix = _getRegionToOutlineMatrix(viewState);
|
||||
final points = region.corners.map(regionToOutlineMatrix.transformOffset).toList();
|
||||
|
|
|
@ -16,7 +16,7 @@ class ScaleBoundaries extends Equatable {
|
|||
final ScaleLevel _initialScale;
|
||||
final Size viewportSize;
|
||||
final Size contentSize;
|
||||
final EdgeInsets padding;
|
||||
final EdgeInsets Function(double scale)? padding;
|
||||
final Matrix4? externalTransform;
|
||||
|
||||
static const Alignment basePosition = Alignment.center;
|
||||
|
@ -31,7 +31,7 @@ class ScaleBoundaries extends Equatable {
|
|||
required ScaleLevel initialScale,
|
||||
required this.viewportSize,
|
||||
required this.contentSize,
|
||||
this.padding = EdgeInsets.zero,
|
||||
this.padding,
|
||||
this.externalTransform,
|
||||
}) : _allowOriginalScaleBeyondRange = allowOriginalScaleBeyondRange,
|
||||
_minScale = minScale,
|
||||
|
@ -45,7 +45,7 @@ class ScaleBoundaries extends Equatable {
|
|||
initialScale: ScaleLevel(ref: ScaleReference.contained),
|
||||
viewportSize: Size.zero,
|
||||
contentSize: Size.zero,
|
||||
padding: EdgeInsets.zero,
|
||||
padding: null,
|
||||
);
|
||||
|
||||
ScaleBoundaries copyWith({
|
||||
|
@ -55,7 +55,7 @@ class ScaleBoundaries extends Equatable {
|
|||
ScaleLevel? initialScale,
|
||||
Size? viewportSize,
|
||||
Size? contentSize,
|
||||
EdgeInsets? padding,
|
||||
EdgeInsets Function(double scale)? padding,
|
||||
Matrix4? externalTransform,
|
||||
}) {
|
||||
return ScaleBoundaries(
|
||||
|
@ -115,7 +115,8 @@ class ScaleBoundaries extends Equatable {
|
|||
|
||||
final minX = ((positionX - 1).abs() / 2) * widthDiff * -1;
|
||||
final maxX = ((positionX + 1).abs() / 2) * widthDiff;
|
||||
return EdgeRange(minX - padding.left, maxX + padding.right);
|
||||
final _padding = padding?.call(scale) ?? EdgeInsets.zero;
|
||||
return EdgeRange(minX - _padding.left, maxX + _padding.right);
|
||||
}
|
||||
|
||||
EdgeRange getYEdges({required double scale}) {
|
||||
|
@ -127,7 +128,8 @@ class ScaleBoundaries extends Equatable {
|
|||
|
||||
final minY = ((positionY - 1).abs() / 2) * heightDiff * -1;
|
||||
final maxY = ((positionY + 1).abs() / 2) * heightDiff;
|
||||
return EdgeRange(minY - padding.top, maxY + padding.bottom);
|
||||
final _padding = padding?.call(scale) ?? EdgeInsets.zero;
|
||||
return EdgeRange(minY - _padding.top, maxY + _padding.bottom);
|
||||
}
|
||||
|
||||
double clampScale(double scale) {
|
||||
|
|
Loading…
Reference in a new issue