Objective-C:刮擦并揭示背后的图像

时间:2012-06-20 13:34:20

标签: ios user-interface

我不知道什么是正确的标题,但这就像是一个划痕和揭示的东西。

这就是它的样子。我必须重叠UIImageViews,现在我要做的是擦除视图的某些部分,其中触摸点是显示背后的图像。它类似于触摸上的绘图,但它的作用是它会删除某些点而不是绘制它。

我尝试在网上搜索但我找不到任何东西。

有人有想法吗?

2 个答案:

答案 0 :(得分:9)

github上有一个很棒的控件,它是MIT Licensed。可能会帮助你了解一下,

https://github.com/akopanev/iOS-Scratch-n-See

祝你好运!

答案 1 :(得分:1)

如果您决定自己动手,那么这只是一个有两个图像的过程,一个完全显示划痕,另一个完全隐藏划痕部分。您可以将这两个图像直接呈现在彼此之上,根据手势识别器更新并将蒙版应用于前方图像。 (您可以先完全遮住前面的图像,然后在用户划伤时取消遮罩部分,或者像我在这里一样,完全显示前面的图像,并在用户划伤时将部分遮挡掉。)无论如何,当您更新/应用时掩盖前面的图像,这将决定后方图像将显示多少。

我不是Core Graphics的人,但它可能看起来像:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIImage *backgroundImage = [UIImage imageNamed:@"imgres-1.jpg"];

    _foregroundImage = [UIImage imageNamed:@"imgres-2.jpg"];

    CGRect frame = CGRectMake((self.view.frame.size.width - _foregroundImage.size.width) / 2.0, 
                              (self.view.frame.size.height - _foregroundImage.size.height) / 2.0, 
                              _foregroundImage.size.width, 
                              _foregroundImage.size.height);

    UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:frame];
    backgroundImageView.image = backgroundImage;
    [self.view addSubview:backgroundImageView];

    _foregroundImageMask = [self createBlankMaskForImage:_foregroundImage];

    UIImageView *_foregroundImageView = [[UIImageView alloc] initWithFrame:frame];
    _foregroundImageView.image = [self maskImage:_foregroundImage withMask:_foregroundImageMask]; // _foregroundImage;
    [self.view addSubview:_foregroundImageView];

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    _foregroundImageView.userInteractionEnabled = YES;
    [_foregroundImageView addGestureRecognizer:pan];
}

- (void)pan:(UIPanGestureRecognizer *)sender
{
    static CGPoint lastPoint;
    UIImageView *maskedImageView = (UIImageView*)sender.view;
    CGPoint location = [sender locationInView:maskedImageView];

    if (sender.state == UIGestureRecognizerStateBegan)
    {
        lastPoint = location;
    } 
    else if (sender.state == UIGestureRecognizerStateChanged)
    {
        UIGraphicsBeginImageContext(_foregroundImage.size);

        CGContextRef context = UIGraphicsGetCurrentContext();
        [_foregroundImageMask drawInRect:maskedImageView.bounds];
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetLineWidth(context, 24.0);
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextBeginPath(context);
        CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(context, location.x, location.y);
        CGContextStrokePath(context);
        _foregroundImageMask = UIGraphicsGetImageFromCurrentImageContext();

        maskedImageView.image = [self maskImage:_foregroundImage withMask:_foregroundImageMask];

        lastPoint = location;
    }
}

- (UIImage *)createBlankMaskForImage:(UIImage *)image
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

    CGContextRef context = CGBitmapContextCreate (NULL, image.size.width, image.size.height,
                                                  8, 0, colorSpace, kCGImageAlphaNone);
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.0); // don't use alpha
    CGContextFillRect(context, CGRectMake(0.0, 0.0, image.size.width, image.size.height));
    CGImageRef imageref = CGBitmapContextCreateImage(context);
    UIImage *result = [UIImage imageWithCGImage:imageref];

    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    CFRelease(imageref);

    return result;
}

// the following came from http://mobiledevelopertips.com/cocoa/how-to-mask-an-image.html

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage 
{
    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);

    UIImage *result = [UIImage imageWithCGImage:masked];

    CGImageRelease(masked);
    CGImageRelease(mask);

    return result;
}

可能很明显,但这使用了两个ivars:

UIImage *_foregroundImage;
UIImage *_foregroundImageMask;

这不是一个非常优雅的实现,但它为您提供了基本的想法。你可以随意使用它。