@@ -28,21 +28,23 @@ private void InitImageLayout(bool animate = false)
28
28
_restrictedCropRect = new Rect ( 0 , 0 , Source . PixelWidth , Source . PixelHeight ) ;
29
29
if ( IsValidRect ( _restrictedCropRect ) )
30
30
{
31
- _currentCroppedRect = KeepAspectRatio ? GetUniformRect ( _restrictedCropRect , UsedAspectRatio ) : _restrictedCropRect ;
31
+ _currentCroppedRect = KeepAspectRatio ? GetUniformRect ( _restrictedCropRect , ActualAspectRatio ) : _restrictedCropRect ;
32
32
UpdateImageLayout ( animate ) ;
33
33
}
34
34
}
35
35
36
36
UpdateThumbsVisibility ( ) ;
37
37
}
38
38
39
+ private bool ShouldUpdateImageLayout => Source != null && IsValidRect ( CanvasRect ) ;
40
+
39
41
/// <summary>
40
42
/// Update image source transform.
41
43
/// </summary>
42
44
/// <param name="animate">Whether animation is enabled.</param>
43
45
private void UpdateImageLayout ( bool animate = false )
44
46
{
45
- if ( Source != null && IsValidRect ( CanvasRect ) )
47
+ if ( ShouldUpdateImageLayout )
46
48
{
47
49
var uniformSelectedRect = GetUniformRect ( CanvasRect , _currentCroppedRect . Width / _currentCroppedRect . Height ) ;
48
50
UpdateImageLayoutWithViewport ( uniformSelectedRect , _currentCroppedRect , animate ) ;
@@ -105,7 +107,7 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
105
107
double radian = 0d , diffPointRadian = 0d ;
106
108
if ( KeepAspectRatio )
107
109
{
108
- radian = Math . Atan ( UsedAspectRatio ) ;
110
+ radian = Math . Atan ( ActualAspectRatio ) ;
109
111
diffPointRadian = Math . Atan ( diffPos . X / diffPos . Y ) ;
110
112
}
111
113
@@ -117,8 +119,8 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
117
119
case ThumbPosition . Top :
118
120
if ( KeepAspectRatio )
119
121
{
120
- var originSizeChange = new Point ( - diffPos . Y * UsedAspectRatio , - diffPos . Y ) ;
121
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
122
+ var originSizeChange = new Point ( - diffPos . Y * ActualAspectRatio , - diffPos . Y ) ;
123
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
122
124
startPoint . X += - safeChange . X / 2 ;
123
125
endPoint . X += safeChange . X / 2 ;
124
126
startPoint . Y += - safeChange . Y ;
@@ -132,8 +134,8 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
132
134
case ThumbPosition . Bottom :
133
135
if ( KeepAspectRatio )
134
136
{
135
- var originSizeChange = new Point ( diffPos . Y * UsedAspectRatio , diffPos . Y ) ;
136
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
137
+ var originSizeChange = new Point ( diffPos . Y * ActualAspectRatio , diffPos . Y ) ;
138
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
137
139
startPoint . X += - safeChange . X / 2 ;
138
140
endPoint . X += safeChange . X / 2 ;
139
141
endPoint . Y += safeChange . Y ;
@@ -147,8 +149,8 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
147
149
case ThumbPosition . Left :
148
150
if ( KeepAspectRatio )
149
151
{
150
- var originSizeChange = new Point ( - diffPos . X , - diffPos . X / UsedAspectRatio ) ;
151
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
152
+ var originSizeChange = new Point ( - diffPos . X , - diffPos . X / ActualAspectRatio ) ;
153
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
152
154
startPoint . Y += - safeChange . Y / 2 ;
153
155
endPoint . Y += safeChange . Y / 2 ;
154
156
startPoint . X += - safeChange . X ;
@@ -162,8 +164,8 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
162
164
case ThumbPosition . Right :
163
165
if ( KeepAspectRatio )
164
166
{
165
- var originSizeChange = new Point ( diffPos . X , diffPos . X / UsedAspectRatio ) ;
166
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
167
+ var originSizeChange = new Point ( diffPos . X , diffPos . X / ActualAspectRatio ) ;
168
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
167
169
startPoint . Y += - safeChange . Y / 2 ;
168
170
endPoint . Y += safeChange . Y / 2 ;
169
171
endPoint . X += safeChange . X ;
@@ -179,7 +181,7 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
179
181
{
180
182
var effectiveLength = diffPos . Y / Math . Cos ( diffPointRadian ) * Math . Cos ( diffPointRadian - radian ) ;
181
183
var originSizeChange = new Point ( - effectiveLength * Math . Sin ( radian ) , - effectiveLength * Math . Cos ( radian ) ) ;
182
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
184
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
183
185
diffPos . X = - safeChange . X ;
184
186
diffPos . Y = - safeChange . Y ;
185
187
}
@@ -193,7 +195,7 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
193
195
diffPointRadian = - diffPointRadian ;
194
196
var effectiveLength = diffPos . Y / Math . Cos ( diffPointRadian ) * Math . Cos ( diffPointRadian - radian ) ;
195
197
var originSizeChange = new Point ( - effectiveLength * Math . Sin ( radian ) , - effectiveLength * Math . Cos ( radian ) ) ;
196
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
198
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
197
199
diffPos . X = safeChange . X ;
198
200
diffPos . Y = - safeChange . Y ;
199
201
}
@@ -207,7 +209,7 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
207
209
diffPointRadian = - diffPointRadian ;
208
210
var effectiveLength = diffPos . Y / Math . Cos ( diffPointRadian ) * Math . Cos ( diffPointRadian - radian ) ;
209
211
var originSizeChange = new Point ( effectiveLength * Math . Sin ( radian ) , effectiveLength * Math . Cos ( radian ) ) ;
210
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
212
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
211
213
diffPos . X = - safeChange . X ;
212
214
diffPos . Y = safeChange . Y ;
213
215
}
@@ -220,7 +222,7 @@ private void UpdateCroppedRect(ThumbPosition position, Point diffPos)
220
222
{
221
223
var effectiveLength = diffPos . Y / Math . Cos ( diffPointRadian ) * Math . Cos ( diffPointRadian - radian ) ;
222
224
var originSizeChange = new Point ( effectiveLength * Math . Sin ( radian ) , effectiveLength * Math . Cos ( radian ) ) ;
223
- var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , UsedAspectRatio ) ;
225
+ var safeChange = GetSafeSizeChangeWhenKeepAspectRatio ( _restrictedSelectRect , position , currentSelectedRect , originSizeChange , ActualAspectRatio ) ;
224
226
diffPos . X = safeChange . X ;
225
227
diffPos . Y = safeChange . Y ;
226
228
}
@@ -293,8 +295,8 @@ private void UpdateSelectedRect(Point startPoint, Point endPoint, bool animate =
293
295
_startY = startPoint . Y ;
294
296
_endX = endPoint . X ;
295
297
_endY = endPoint . Y ;
296
- var centerX = ( ( _endX - _startX ) / 2 ) + _startX ;
297
- var centerY = ( ( _endY - _startY ) / 2 ) + _startY ;
298
+ var center = SelectionAreaCenter ;
299
+
298
300
Storyboard storyboard = null ;
299
301
if ( animate )
300
302
{
@@ -305,12 +307,12 @@ private void UpdateSelectedRect(Point startPoint, Point endPoint, bool animate =
305
307
{
306
308
if ( animate )
307
309
{
308
- storyboard . Children . Add ( CreateDoubleAnimation ( centerX , _animationDuration , _topThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
310
+ storyboard . Children . Add ( CreateDoubleAnimation ( center . X , _animationDuration , _topThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
309
311
storyboard . Children . Add ( CreateDoubleAnimation ( _startY , _animationDuration , _topThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
310
312
}
311
313
else
312
314
{
313
- _topThumb . X = centerX ;
315
+ _topThumb . X = center . X ;
314
316
_topThumb . Y = _startY ;
315
317
}
316
318
}
@@ -319,12 +321,12 @@ private void UpdateSelectedRect(Point startPoint, Point endPoint, bool animate =
319
321
{
320
322
if ( animate )
321
323
{
322
- storyboard . Children . Add ( CreateDoubleAnimation ( centerX , _animationDuration , _bottomThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
324
+ storyboard . Children . Add ( CreateDoubleAnimation ( center . X , _animationDuration , _bottomThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
323
325
storyboard . Children . Add ( CreateDoubleAnimation ( _endY , _animationDuration , _bottomThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
324
326
}
325
327
else
326
328
{
327
- _bottomThumb . X = centerX ;
329
+ _bottomThumb . X = center . X ;
328
330
_bottomThumb . Y = _endY ;
329
331
}
330
332
}
@@ -334,12 +336,12 @@ private void UpdateSelectedRect(Point startPoint, Point endPoint, bool animate =
334
336
if ( animate )
335
337
{
336
338
storyboard . Children . Add ( CreateDoubleAnimation ( _startX , _animationDuration , _leftThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
337
- storyboard . Children . Add ( CreateDoubleAnimation ( centerY , _animationDuration , _leftThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
339
+ storyboard . Children . Add ( CreateDoubleAnimation ( center . Y , _animationDuration , _leftThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
338
340
}
339
341
else
340
342
{
341
343
_leftThumb . X = _startX ;
342
- _leftThumb . Y = centerY ;
344
+ _leftThumb . Y = center . Y ;
343
345
}
344
346
}
345
347
@@ -348,12 +350,12 @@ private void UpdateSelectedRect(Point startPoint, Point endPoint, bool animate =
348
350
if ( animate )
349
351
{
350
352
storyboard . Children . Add ( CreateDoubleAnimation ( _endX , _animationDuration , _rightThumb , nameof ( ImageCropperThumb . X ) , true ) ) ;
351
- storyboard . Children . Add ( CreateDoubleAnimation ( centerY , _animationDuration , _rightThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
353
+ storyboard . Children . Add ( CreateDoubleAnimation ( center . Y , _animationDuration , _rightThumb , nameof ( ImageCropperThumb . Y ) , true ) ) ;
352
354
}
353
355
else
354
356
{
355
357
_rightThumb . X = _endX ;
356
- _rightThumb . Y = centerY ;
358
+ _rightThumb . Y = center . Y ;
357
359
}
358
360
}
359
361
@@ -504,61 +506,74 @@ private void UpdateMaskArea(bool animate = false)
504
506
} ;
505
507
}
506
508
509
+ private bool ShouldUpdateAspectRatio => KeepAspectRatio && Source != null && IsValidRect ( _restrictedSelectRect ) ;
510
+
507
511
/// <summary>
508
512
/// Update image aspect ratio.
509
513
/// </summary>
510
514
private void UpdateAspectRatio ( bool animate = false )
511
515
{
512
- if ( KeepAspectRatio && Source != null && IsValidRect ( _restrictedSelectRect ) )
513
- {
514
- var centerX = ( ( _endX - _startX ) / 2 ) + _startX ;
515
- var centerY = ( ( _endY - _startY ) / 2 ) + _startY ;
516
- var restrictedMinLength = MinCroppedPixelLength * _imageTransform . ScaleX ;
517
- var maxSelectedLength = Math . Max ( _endX - _startX , _endY - _startY ) ;
518
- var viewRect = new Rect ( centerX - ( maxSelectedLength / 2 ) , centerY - ( maxSelectedLength / 2 ) , maxSelectedLength , maxSelectedLength ) ;
519
- var uniformSelectedRect = GetUniformRect ( viewRect , UsedAspectRatio ) ;
520
- if ( uniformSelectedRect . Width > _restrictedSelectRect . Width || uniformSelectedRect . Height > _restrictedSelectRect . Height )
521
- {
522
- uniformSelectedRect = GetUniformRect ( _restrictedSelectRect , UsedAspectRatio ) ;
523
- }
516
+ if ( ! ShouldUpdateAspectRatio )
517
+ {
518
+ return ;
519
+ }
524
520
525
- if ( uniformSelectedRect . Width < restrictedMinLength || uniformSelectedRect . Height < restrictedMinLength )
526
- {
527
- var scale = restrictedMinLength / Math . Min ( uniformSelectedRect . Width , uniformSelectedRect . Height ) ;
528
- uniformSelectedRect . Width *= scale ;
529
- uniformSelectedRect . Height *= scale ;
530
- if ( uniformSelectedRect . Width > _restrictedSelectRect . Width || uniformSelectedRect . Height > _restrictedSelectRect . Height )
531
- {
532
- AspectRatio = - 1 ;
533
- return ;
534
- }
535
- }
521
+ var center = SelectionAreaCenter ;
522
+ var restrictedMinLength = MinCroppedPixelLength * _imageTransform . ScaleX ;
523
+ var maxSelectedLength = Math . Max ( _endX - _startX , _endY - _startY ) ;
524
+ var viewRect = new Rect ( center . X - ( maxSelectedLength / 2 ) , center . Y - ( maxSelectedLength / 2 ) , maxSelectedLength , maxSelectedLength ) ;
536
525
537
- if ( _restrictedSelectRect . X > uniformSelectedRect . X )
538
- {
539
- uniformSelectedRect . X += _restrictedSelectRect . X - uniformSelectedRect . X ;
540
- }
526
+ var uniformSelectedRect = GetUniformRect ( viewRect , ActualAspectRatio ) ;
527
+ if ( uniformSelectedRect . Width > _restrictedSelectRect . Width || uniformSelectedRect . Height > _restrictedSelectRect . Height )
528
+ {
529
+ uniformSelectedRect = GetUniformRect ( _restrictedSelectRect , ActualAspectRatio ) ;
530
+ }
541
531
542
- if ( _restrictedSelectRect . Y > uniformSelectedRect . Y )
543
- {
544
- uniformSelectedRect . Y += _restrictedSelectRect . Y - uniformSelectedRect . Y ;
545
- }
532
+ // If selection area is smaller than allowed.
533
+ if ( uniformSelectedRect . Width < restrictedMinLength || uniformSelectedRect . Height < restrictedMinLength )
534
+ {
535
+ // Scale selection area to fit.
536
+ var scale = restrictedMinLength / Math . Min ( uniformSelectedRect . Width , uniformSelectedRect . Height ) ;
537
+ uniformSelectedRect . Width *= scale ;
538
+ uniformSelectedRect . Height *= scale ;
546
539
547
- if ( ( _restrictedSelectRect . X + _restrictedSelectRect . Width ) < ( uniformSelectedRect . X + uniformSelectedRect . Width ) )
540
+ // If selection area is larger than allowed.
541
+ if ( uniformSelectedRect . Width > _restrictedSelectRect . Width || uniformSelectedRect . Height > _restrictedSelectRect . Height )
548
542
{
549
- uniformSelectedRect . X += ( _restrictedSelectRect . X + _restrictedSelectRect . Width ) - ( uniformSelectedRect . X + uniformSelectedRect . Width ) ;
543
+ // Sentinal value. Equivelant to setting KeepAspectRatio to false. Causes AspectRatio to be recalculated.
544
+ AspectRatio = - 1 ;
545
+ return ;
550
546
}
547
+ }
551
548
552
- if ( ( _restrictedSelectRect . Y + _restrictedSelectRect . Height ) < ( uniformSelectedRect . Y + uniformSelectedRect . Height ) )
553
- {
554
- uniformSelectedRect . Y += ( _restrictedSelectRect . Y + _restrictedSelectRect . Height ) - ( uniformSelectedRect . Y + uniformSelectedRect . Height ) ;
555
- }
549
+ // Fix positioning
550
+ if ( _restrictedSelectRect . X > uniformSelectedRect . X )
551
+ {
552
+ uniformSelectedRect . X += _restrictedSelectRect . X - uniformSelectedRect . X ;
553
+ }
556
554
557
- var croppedRect = _inverseImageTransform . TransformBounds ( uniformSelectedRect ) ;
558
- croppedRect . Intersect ( _restrictedCropRect ) ;
559
- _currentCroppedRect = croppedRect ;
560
- UpdateImageLayout ( animate ) ;
555
+ if ( _restrictedSelectRect . Y > uniformSelectedRect . Y )
556
+ {
557
+ uniformSelectedRect . Y += _restrictedSelectRect . Y - uniformSelectedRect . Y ;
561
558
}
559
+
560
+ // Fix size
561
+ if ( ( _restrictedSelectRect . X + _restrictedSelectRect . Width ) < ( uniformSelectedRect . X + uniformSelectedRect . Width ) )
562
+ {
563
+ uniformSelectedRect . X += ( _restrictedSelectRect . X + _restrictedSelectRect . Width ) - ( uniformSelectedRect . X + uniformSelectedRect . Width ) ;
564
+ }
565
+
566
+ if ( ( _restrictedSelectRect . Y + _restrictedSelectRect . Height ) < ( uniformSelectedRect . Y + uniformSelectedRect . Height ) )
567
+ {
568
+ uniformSelectedRect . Y += ( _restrictedSelectRect . Y + _restrictedSelectRect . Height ) - ( uniformSelectedRect . Y + uniformSelectedRect . Height ) ;
569
+ }
570
+
571
+ // Apply transformation
572
+ var croppedRect = _inverseImageTransform . TransformBounds ( uniformSelectedRect ) ;
573
+ croppedRect . Intersect ( _restrictedCropRect ) ;
574
+ _currentCroppedRect = croppedRect ;
575
+
576
+ UpdateImageLayout ( animate ) ;
562
577
}
563
578
564
579
/// <summary>
@@ -632,5 +647,10 @@ private void UpdateThumbsVisibility()
632
647
_lowerRigthThumb . Visibility = cornerThumbsVisibility ;
633
648
}
634
649
}
650
+
651
+ /// <summary>
652
+ /// Gets a value that indicates the center of the visible selection rectangle.
653
+ /// </summary>
654
+ private Point SelectionAreaCenter => new Point ( ( ( _endX - _startX ) / 2 ) + _startX , ( ( _endY - _startY ) / 2 ) + _startY ) ;
635
655
}
636
656
}
0 commit comments