Through 这个问题和答案 https://stackoverflow.com/questions/26821725/determine-if-crop-rect-is-entirely-contained-within-rotated-uiview?lq=1#26822021我现在有了一种有效的方法来检测任意旋转的图像何时不完全超出裁剪矩形。
下一步是弄清楚如何正确调整它包含的滚动视图缩放,以确保裁剪矩形内没有空白区域。为了澄清一下,我想放大(放大)图像;裁剪矩形应保持不变。
布局层次结构如下所示:
containing UIScrollView
UIImageView (this gets arbitrarily rotated)
crop rect overlay view
... UIImageView 也可以在滚动视图内缩放和平移。
需要考虑发生 4 个手势事件:
- 平移手势(完成):通过检测平移是否不正确并重置 contentOffset 来完成。
- 旋转 CGAffineTransform
- 滚动视图缩放
- 裁剪矩形叠加框的调整
据我所知,我应该能够对 2、3 和 4 使用相同的逻辑来调整滚动视图的 ZoomScale 以使图像正确适合。
如何正确计算使旋转图像完全适合裁剪矩形所需的缩放比例?
为了更好地说明我想要完成的任务,这里有一个错误大小的示例:
我需要计算使其看起来像这样所需的缩放比例:
这是我迄今为止使用下面 Oluseyi 的解决方案获得的代码。当旋转角度很小(例如小于 1 弧度)时它会起作用,但超过这个角度就会变得非常不稳定。
CGRect visibleRect = [_scrollView convertRect:_scrollView.bounds toView:_imageView];
CGRect cropRect = _cropRectView.frame;
CGFloat rotationAngle = fabs(self.rotationAngle);
CGFloat a = visibleRect.size.height * sinf(rotationAngle);
CGFloat b = visibleRect.size.width * cosf(rotationAngle);
CGFloat c = visibleRect.size.height * cosf(rotationAngle);
CGFloat d = visibleRect.size.width * sinf(rotationAngle);
CGFloat zoomDiff = MAX(cropRect.size.width / (a + b), cropRect.size.height / (c + d));
CGFloat newZoomScale = (zoomDiff > 1) ? zoomDiff : 1.0 / zoomDiff;
[UIView animateWithDuration:0.2
delay:0.05
options:NO
animations:^{
[self centerToCropRect:[self convertRect:cropRect toView:self.zoomingView]];
_scrollView.zoomScale = _scrollView.zoomScale * newZoomScale;
} completion:^(BOOL finished) {
if (![self rotatedView:_imageView containsViewCompletely:_cropRectView])
{
// Damn, it's still broken - this happens a lot
}
else
{
// Woo! Fixed
}
_didDetectBadRotation = NO;
}];
请注意,我使用的是自动布局,这使得框架和边界变得愚蠢。