在滚动视图内缩放旋转图像以适合(填充)叠加矩形的帧 [英] Zoom a rotated image inside scroll view to fit (fill) frame of overlay rect

查看:122
本文介绍了在滚动视图内缩放旋转图像以适合(填充)叠加矩形的帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过这个问题并回答我现在有一种工作方法可以检测任意旋转的图像何时不在裁剪矩形之外。

Through this question and answer I've now got a working means of detecting when an arbitrarily rotated image isn't completely outside a cropping rect.

下一步是弄清楚如何正确调整它包含滚动视图缩放,以确保裁剪矩形内没有空格。为了澄清,我想放大(放大)图像;裁剪矩形应保持未变换。

The next step is to figure out how to correctly adjust it's containing scroll view zoom to ensure that there are no empty spaces inside the cropping rect. To clarify, I want to enlarge (zoom in) the image; the crop rect should remain un-transformed.

布局层次结构如下所示:

The layout hierarchy looks like this:

containing UIScrollView
    UIImageView (this gets arbitrarily rotated)
        crop rect overlay view

...其中UIImageView也可以在scrollView中进行缩放和平移。

... where the UIImageView can also be zoomed and panned inside the scrollView.

有4个手势事件需要考虑:

There are 4 gesture events that occur that need to be accounted for:


  1. 平移手势(完成):通过检测它是否被错误平移并重置contentOffset来完成。

  2. 旋转CGAffineTransform

  3. 滚动视图缩放

  4. 调整裁剪矩形覆盖框架

  1. Pan gesture (done): accomplished by detecting if it's been panned incorrectly and resets the contentOffset.
  2. Rotation CGAffineTransform
  3. Scroll view zoom
  4. Adjustment of the cropping rect overlay frame

据我所知,我应该能够使用2,3和4的相同逻辑来调整滚动视图的zoomScale,以使图像正确匹配。

As far as I can tell, I should be able to use the same logic for 2, 3, and 4 to adjust the zoomScale of the scroll view to make the image fit properly.

如何正确计算旋转图像所需的缩放比率完全在裁剪矩内吗?

为了更好地说明我想要完成的事情,这里有一个不正确尺寸的例子:

To better illustrate what I'm trying to accomplish, here's an example of the incorrect size:

我需要计算必要的缩放比例,使它看起来像这样:

I need to calculate the zoom ratio necessary to make it look like this:

这是我到目前为止使用Oluseyi解决方案获得的代码。它适用于旋转角度较小(例如小于1弧度)的情况,但任何超过它的情况都会变得非常糟糕。

Here's the code I've got so far using Oluseyi's solution below. It works when the rotation angle is minor (e.g. less than 1 radian), but anything over that and it goes really wonky.

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;
                 }];

注意我正在使用AutoLayout,这使得帧和边界变得很傻。

Note I'm using AutoLayout which makes frames and bounds goofy.

推荐答案

假设您的图像矩形(图中的蓝色)和裁剪矩形(红色)具有相同的纵横比和中心。旋转时,图像矩形现在有一个边界矩形(绿色),这是您希望裁剪缩放到的(有效地,缩小图像)。

Assume your image rectangle (blue in the diagram) and crop rectangle (red) have the same aspect ratio and center. When rotated, the image rectangle now has a bounding rectangle (green) which is what you want your crop scaled to (effectively, by scaling down the image).

要缩放有效地,您需要知道新边界矩形的尺寸,并使用适合裁剪矩形的比例因子。边界矩形的尺寸显然是

To scale effectively, you need to know the dimensions of the new bounding rectangle and use a scale factor that fits the crop rect into it. The dimensions of the bounding rectangle are rather obviously

(a + b) x (c + d)

请注意,每个段a,b,c,d是由边界矩形成的直角三角形的相邻或相对侧和旋转的图像rect。

Notice that each segment a, b, c, d is either the adjacent or opposite side of a right triangle formed by the bounding rect and the rotated image rect.

a = image_rect_height * sin(rotation_angle)
b = image_rect_width * cos(rotation_angle)
c = image_rect_width * sin(rotation_angle)
d = image_rect_height * cos(rotation_angle)

您的比例因子只是

MAX(crop_rect_width / (a + b), crop_rect_height / (c + d))

以下是参考图:

这篇关于在滚动视图内缩放旋转图像以适合(填充)叠加矩形的帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆