Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在滚动视图内缩放旋转图像,以适应(填充)覆盖矩形的框架_Ios_Objective C_Uiscrollview_Cgaffinetransform - Fatal编程技术网

Ios 在滚动视图内缩放旋转图像,以适应(填充)覆盖矩形的框架

Ios 在滚动视图内缩放旋转图像,以适应(填充)覆盖矩形的框架,ios,objective-c,uiscrollview,cgaffinetransform,Ios,Objective C,Uiscrollview,Cgaffinetransform,现在我有了一种有效的方法来检测任意旋转的图像是否完全在裁剪矩形之外 下一步是找出如何正确调整它包含的滚动视图缩放,以确保裁剪矩形内没有空白。为了澄清,我想放大(放大)图像;裁剪矩形应保持未转换状态 布局层次结构如下所示: containing UIScrollView UIImageView (this gets arbitrarily rotated) crop rect overlay view 。。。其中UIImageView也可以在scrollView中缩放和平

现在我有了一种有效的方法来检测任意旋转的图像是否完全在裁剪矩形之外

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

布局层次结构如下所示:

containing UIScrollView
    UIImageView (this gets arbitrarily rotated)
        crop rect overlay view
。。。其中UIImageView也可以在scrollView中缩放和平移

需要说明发生的4个手势事件:

  • 平移手势(完成):通过检测平移是否错误并重置contentOffset来完成
  • 旋转仿射变换
  • 滚动视图缩放
  • 裁剪矩形覆盖框的调整
  • 据我所知,我应该能够使用2、3和4的相同逻辑来调整滚动视图的缩放比例,以使图像正确匹配

    如何正确计算使旋转图像完全适合裁剪矩形所需的缩放比?

    为了更好地说明我试图实现的目标,下面是一个大小不正确的示例:

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

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

    下面是我使用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;
                     }];
    

    注意,我使用的是自动布局,它会使框架和边界变得愚蠢。

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

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

    (a + b) x (c + d)
    
    请注意,每个线段a、b、c、d都是由边界矩形和旋转图像矩形形成的直角三角形的相邻边或相对边

    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))
    
    这是一个参考图:


    覆盖矩形的填充框:

    对于方形裁剪,您需要知道旋转图像的新边界,这将填充裁剪视图

    让我们看一下参考图: 您需要找到直角三角形的高度(图号2)。两个高度相等

    CGFloat sinAlpha = sin(alpha);
    CGFloat cosAlpha = cos(alpha);
    CGFloat hypotenuse = /* calculate */;
    CGFloat altitude = hypotenuse * sinAlpha * cosAlpha;
    
    然后,需要计算旋转图像的新宽度和所需的比例因子,如下所示:

     CGFloat newWidth = previousWidth + altitude * 2;
     CGFloat scale = newWidth / previousWidth;
    

    我已经实现了这个方法。

    我将使用示例代码来回答,但如果您考虑旋转视图坐标系,这个问题基本上变得非常简单

    UIView* container = [[UIView alloc] initWithFrame:CGRectMake(80, 200, 100, 100)];
    container.backgroundColor = [UIColor blueColor];
    
    UIView* content2 = [[UIView alloc] initWithFrame:CGRectMake(-50, -50, 150, 150)];
    content2.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.5];
    [container addSubview:content2];
    
    [self.view setBackgroundColor:[UIColor blackColor]];
    [self.view addSubview:container];
    
    [container.layer setSublayerTransform:CATransform3DMakeRotation(M_PI / 8.0, 0, 0, 1)];
    
    //And now the calculations
    CGRect containerFrameInContentCoordinates = [content2 convertRect:container.bounds fromView:container];
    CGRect unionBounds = CGRectUnion(content2.bounds, containerFrameInContentCoordinates);
    
    CGFloat midX = CGRectGetMidX(content2.bounds);
    CGFloat midY = CGRectGetMidY(content2.bounds);
    
    CGFloat scaleX1 = (-1 * CGRectGetMinX(unionBounds) + midX) / midX;
    CGFloat scaleX2 = (CGRectGetMaxX(unionBounds) - midX) / midX;
    CGFloat scaleY1 = (-1 * CGRectGetMinY(unionBounds) + midY) / midY;
    CGFloat scaleY2 = (CGRectGetMaxY(unionBounds) - midY) / midY;
    
    CGFloat scaleX = MAX(scaleX1, scaleX2);
    CGFloat scaleY = MAX(scaleY1, scaleY2);
    CGFloat scale = MAX(scaleX, scaleY);
    
    content2.transform = CGAffineTransformScale(content2.transform, scale, scale);
    

    图像视图只是围绕其中心旋转,还是可以进行平移?@robmayoff它也可以进行平移,但如果我能够基于中心旋转使其工作,那将是一个巨大的开始。然后,我可以使用相同的计算方法比较作物视图的中心或其他东西。对于其他任何看赏金的人来说,下面的Oluseyi的答案肯定部分有效,但不完全有效。您可以随意添加其他答案。您找到怎么做了吗?@brandonscript您找到了吗?