根据UIPinch

时间:2016-01-26 03:30:27

标签: ios objective-c uiimageview uipangesturerecognizer uipinchgesturerecognizer

我对如何做我需要的东西感到很困惑!任何帮助非常感谢!我有一个透明的图像叠加层,后面有另一个图像,它附有一个UIPanGestureRecognizer和一个UIPinchGestureRecognizer。顶部图像有一个完全透明的中间,作为"玻璃"视图。我正在尝试将底部图像裁剪为" glass"部分基于平移和捏。 (见下图,看看我正在谈论的内容)我已经成功地处理了平底锅作物,但是在应用捏合时也有问题正确裁剪。

我没有使用snapshotViewAfterScreenUpdates。

这是我到目前为止的代码:

 UIImage *snapshotImage;

/* draw the image of all the views below our view */
UIGraphicsBeginImageContextWithOptions(self.pendantImageView.bounds.size, NO, 0);
BOOL successfulDrawHierarchy = [self.pendantImageView drawViewHierarchyInRect:self.pendantImageView.bounds afterScreenUpdates:YES];
if ( successfulDrawHierarchy ) {
    snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
} else {
    NSLog(@"drawViewHierarchyInRect:afterScreenUpdates: failed - there's nothing to draw...");
}
UIGraphicsEndImageContext();
UIImage *croppedImage;
if ( successfulDrawHierarchy ) {

    /* calculate the coordinates of the rectangle we're interested in within the returned image */
    CGRect cropRect = CGRectOffset(pendantFrame, - self.pendantImageView.frame.origin.x, - self.pendantImageView.frame.origin.y);

    /* draw the cropped section with a clipping region */
    UIGraphicsBeginImageContextWithOptions(cropRect.size, YES, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClipToRect(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));
    CGRect targetRectangeForCrop = CGRectMake(-cropRect.origin.x, -cropRect.origin.y, snapshotImage.size.width, snapshotImage.size.height);
    [snapshotImage drawInRect:targetRectangeForCrop];
    croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();  
}

pendantImageView是底部的imageView和pendantFrame是我试图裁剪的区域的中间坐标。

提前致谢!

crop image to the area in the middle

2 个答案:

答案 0 :(得分:3)

我不确定我是否理解正确,但这是我的结果:

(点击视频观看完整版)

Demo CountPages alpha

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIImageView *theImageView = [UIImageView new];
    [self.view addSubview:theImageView];
    theImageView.image = [UIImage imageNamed:@"image1.jpg"];
    theImageView.frame = self.view.frame;
    theImageView.userInteractionEnabled = YES;
    theImageView.alpha = 0.6;

    UIImageView *thePanImageView = [UIImageView new];
    [self.view addSubview:thePanImageView];
    thePanImageView.frame = CGRectMake(0, 0, 100, 100);
    thePanImageView.center = CGPointMake(theImageView.frame.size.width/2, theImageView.frame.size.height/2);
    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
    thePanImageView.userInteractionEnabled = YES;
    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;
    thePanImageView.clipsToBounds = YES;
    thePanImageView.theWeakObject = theImageView;
    {
        UIPanGestureRecognizer *thePanGesture = [UIPanGestureRecognizer new];
        [thePanGesture addTarget:self action:@selector(handlePanGesture:)];
        [thePanImageView addGestureRecognizer:thePanGesture];

        UIPinchGestureRecognizer *thePinchGesture = [UIPinchGestureRecognizer new];
        [thePinchGesture addTarget:self action:@selector(handlePinchGesture:)];
        [thePanImageView addGestureRecognizer:thePinchGesture];
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)thePanGesture
{
    UIImageView *thePanImageView = (id)thePanGesture.view;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePanGesture locationInView:theImageView];

    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)thePinchGesture
{
    UIImageView *thePanImageView = (id)thePinchGesture.view;
    static CGRect theInitialFrame;
    if (thePinchGesture.state == UIGestureRecognizerStateBegan)
    {
        theInitialFrame = thePanImageView.frame;
    }
    else
    {
        CGRect theFrame = theInitialFrame;
        theFrame.size.width *= thePinchGesture.scale;
        theFrame.size.height *= thePinchGesture.scale;
        thePanImageView.frame = theFrame;
    }

    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePinchGesture locationInView:theImageView];

    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
}

- (UIImage * __nonnull)screenshotFromRect:(CGRect)theRect fromView:(UIView * __nonnull)theView;
{
    if (!theView)
    {
        abort();
    }
    if (theRect.size.height < 1 || theRect.size.width < 1)
    {
        abort();
    }

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
    {
        UIGraphicsBeginImageContextWithOptions(theRect.size, YES, [UIScreen mainScreen].scale);
    }
    else
    {
        UIGraphicsBeginImageContext(theRect.size);
    }

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -theRect.origin.x, -theRect.origin.y);
    [theView.layer renderInContext:ctx];

    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}

修改

上述解决方案在CPU方面效率低下,因为每次移动视图时都会截取屏幕截图。

更有效的方法是创建额外的UIImageView,只需将其移到thePanImageView

代码如下:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIImageView *theImageView = [UIImageView new];
    [self.view addSubview:theImageView];
    theImageView.image = [UIImage imageNamed:@"image1.jpg"];
    theImageView.frame = self.view.frame;
    theImageView.userInteractionEnabled = YES;
    theImageView.alpha = 0.6;

    UIImageView *thePanImageView = [UIImageView new];
    [self.view addSubview:thePanImageView];
    thePanImageView.frame = CGRectMake(0, 0, 100, 100);
    thePanImageView.center = CGPointMake(theImageView.frame.size.width/2, theImageView.frame.size.height/2);
    thePanImageView.userInteractionEnabled = YES;
    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;
    thePanImageView.clipsToBounds = YES;
    thePanImageView.layer.borderColor = [UIColor redColor].CGColor;
    thePanImageView.layer.borderWidth = 1;
    thePanImageView.theWeakObject = theImageView;
    {
        UIPanGestureRecognizer *thePanGesture = [UIPanGestureRecognizer new];
        [thePanGesture addTarget:self action:@selector(handlePanGesture:)];
        [thePanImageView addGestureRecognizer:thePanGesture];

        UIPinchGestureRecognizer *thePinchGesture = [UIPinchGestureRecognizer new];
        [thePinchGesture addTarget:self action:@selector(handlePinchGesture:)];
        [thePanImageView addGestureRecognizer:thePinchGesture];

        UIImageView *theExtraImageView = [UIImageView new];
        [thePanImageView addSubview:theExtraImageView];
        theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theImageView.frame.size.width, theImageView.frame.size.height);
        theExtraImageView.image = theImageView.image;
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)thePanGesture
{
    UIImageView *thePanImageView = (id)thePanGesture.view;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePanGesture locationInView:theImageView];

    UIImageView *theExtraImageView = thePanImageView.subviews.firstObject;
    theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theExtraImageView.frame.size.width, theExtraImageView.frame.size.height);
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)thePinchGesture
{
    UIImageView *thePanImageView = (id)thePinchGesture.view;
    static CGRect theInitialFrame;
    if (thePinchGesture.state == UIGestureRecognizerStateBegan)
    {
        theInitialFrame = thePanImageView.frame;
    }
    else
    {
        CGRect theFrame = theInitialFrame;
        theFrame.size.width *= thePinchGesture.scale;
        theFrame.size.height *= thePinchGesture.scale;
        thePanImageView.frame = theFrame;
    }

    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePinchGesture locationInView:theImageView];

    UIImageView *theExtraImageView = thePanImageView.subviews.firstObject;
    theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theExtraImageView.frame.size.width, theExtraImageView.frame.size.height);
}

<强>供参考:

theWeakObject只是NSObject的自定义属性。我使用它是因为我很懒,并且不想创建全局可见的@property

答案 1 :(得分:0)

您应该询问如何输出图像使用遮罩!这是解决方案的链接:

CGContextClipToMask returning blank image

你需要改变:

CGContextClipToRect(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));

类似于:

CGContextClipToMask(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height), maskImage);