【问题标题】:How do I prevent Pinch to Zoom Gestures from auto-rotating my AVCapture layer?如何防止捏到缩放手势自动旋转我的 AVCapture 图层?
【发布时间】:2013-04-02 06:18:37
【问题描述】:

Objective-C,iPhone iOS 6.0

下面的代码很好地支持纵向,但是当我尝试横向时,捏缩放自动将其旋转回尴尬的纵向模式(但在横向视图中)。

@implementation AVCapture
{
    CGFloat     beginGestureScale;
    CGFloat     effectiveScale;
}


- (id)initWithView:(UIView *)cameraView
{
    ......

    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];

    [self rotateToInterfaceOrientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];

    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    self.previewLayer.frame = cameraView.frame;
    [self.previewLayer setPosition:CGPointMake(CGRectGetMidX(cameraView.bounds), CGRectGetMidY(cameraView.bounds))];
    [cameraView.layer addSublayer:self.previewLayer];

    effectiveScale = 1.0;

    ......
}


- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    CALayer *previewLayer = self.previewLayer;

    switch (toInterfaceOrientation)
    {
        case UIDeviceOrientationLandscapeLeft:
            previewLayer.transform = CATransform3DMakeRotation(M_PI+M_PI_2, 0, 0, 1); // 270 degress
            break;

        case UIDeviceOrientationLandscapeRight:
            previewLayer.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1); // 270 degress
            break;

        case UIDeviceOrientationPortraitUpsideDown:
            previewLayer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1); // 270 degress
            break;

        default:
            previewLayer.transform = CATransform3DMakeRotation(0.0, 0, 0, 1); // 270 degress
            break;
    }

}



// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark Pinch to Zoom Gestures
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ( [gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] )
        beginGestureScale = effectiveScale;

    return YES;

}



- (void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer
{
    if ([recognizer numberOfTouches] < 2)
        return;


    BOOL allTouchesAreOnThePreviewLayer = YES;
    NSUInteger numTouches = [recognizer numberOfTouches], i;

    for (i=0; i<numTouches; ++i)
    {
        CGPoint location = [recognizer locationOfTouch:i inView:m_CameraView];
        CGPoint convertedLocation = [self.previewLayer convertPoint:location fromLayer:self.previewLayer.superlayer];

        if (![self.previewLayer containsPoint:convertedLocation])
        {
            allTouchesAreOnThePreviewLayer = NO;
            break;
        }
    }

    if (allTouchesAreOnThePreviewLayer)
    {
        effectiveScale = beginGestureScale * recognizer.scale;

        if (effectiveScale < 1.0)
            effectiveScale = 1.0;

        CGFloat maxScaleAndCropFactor = [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor];

        if (effectiveScale > maxScaleAndCropFactor)
            effectiveScale = maxScaleAndCropFactor;

        [CATransaction begin];
        [CATransaction setAnimationDuration:.025];

        // Scale
        [self.previewLayer setAffineTransform:CGAffineTransformMakeScale(effectiveScale, effectiveScale)];

        [CATransaction commit];
    }

}

我似乎不知道如何保持我的变换。

【问题讨论】:

    标签: iphone ios objective-c


    【解决方案1】:

    类似问题已在此处得到解答:UIView rotates while scaling using CGAffineTransformMakeScale

    在我看来,由于您正在手动旋转previewLayer,因此您需要相应地调整识别器,因为您正在通过缩放覆盖转换。发生这种情况是因为转换是绝对的,或者至少我是这么认为的。

    如何使用CGAffineTransformScale(正如我在链接的问题中所推荐的那样),您可以在其中传递previewLayer 的原始转换以及您想要的比例?

    编辑 以下是此问题的文档:https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGAffineTransform/Reference/reference.html 在那里您可以看到CGAffineTransformMakeScale 用于创建 转换,CGAffineTransformScale 用于更改它们,我相信这就是您所需要的。

    EDIT2

    [UIView animateWithDuration:.25 animations:^{
       self.previewLayer.transform = CGAffineTransformScale(self.previewLayer.transform, effectiveScale, effectiveScale);
                     }];
    

    【讨论】:

    • 我试过了:[self.previewLayer setAffineTransform:CGAffineTransformScale(self.previewLayer.affineTransform, effectiveScale, effectiveScale)]; 但随后缩放会失控。
    • 您能描述一下失控是什么意思吗?转型做的和以前一样吗?
    • 在我捏放大的那一刻,图像迅速放大到像素级,我似乎无法再缩小了。无法使用。
    • 这不应该发生。 effectiveScale 的常用值是什么?还有,你为什么要把recognizer.scalebeginGestureScale相乘,如果我没看错,应该是一样的?
    • 原始代码不是我的,所以我在这里修复它。有效规模急剧上升。就好像变焦需要有一些限制。会不会是因为我自己使用了previewLayer
    【解决方案2】:

    解决了!

    找到this: “...更改预览层的方向不会改变图片的捕获方式。为此需要使用AVCaptureConnection's setVideoOrientation: 方法。”

    .. 和this.

    [captureVideoPreviewLayer.connection setVideoOrientation:self.interfaceOrientation];
    

    所以我替换了这个:

    [self rotateToInterfaceOrientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];
    

    用这个:

    [self.previewLayer.connection setVideoOrientation:[UIDevice currentDevice].orientation];
    

    现在它在横向模式下一切正常+捏缩放。 :)

    【讨论】:

      猜你喜欢
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      相关资源
      最近更新 更多