2

これにぴったりのタイトルはわかりませんが、これはひっかき傷のようなものです。

では、その様子です。UIImageViews をオーバーラップする必要があります。ここでやりたいことは、タッチ ポイントが背後の画像を表示するビューの特定の部分を消去することです。タッチでの描画のようなものですが、描画する代わりに特定のポイントを消去します。

ウェブで検索してみましたが、何も見つかりません。

誰にもアイデアがありますか?

4

2 に答える 2

9

github には素晴らしいコントロールが 1 つあります。それは MIT ライセンスです。ヒントになるかもしれませんが、

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

幸運を!

于 2012-06-20T13:40:28.467 に答える
1

自分でロールすることにした場合、それは2つの画像を作成するプロセスであり、1つはスクラッチが完全に表示され、もう1つはスクラッチ部分が完全に非表示になります。これらの2つの画像を重ねて表示し、ジェスチャ認識機能に基づいて前面の画像にマスクを更新して適用します。(最初に正面の画像を完全にマスクしてから、ユーザーが引っかいたときに部分をマスク解除するか、ここにあるように、正面の画像を完全に表示して、ユーザーが引っかいたときに部分をマスクします。)とにかく、更新/適用するときに前面の画像にマスクを付けます。これにより、背面の画像がどれだけ透けて見えるかが決まります。

私はCoreGraphicsの人ではありませんが、次のようになります。

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

おそらく明らかですが、これは2つのivarを使用します。

UIImage *_foregroundImage;
UIImage *_foregroundImageMask;

これはそれほどエレガントな実装ではありませんが、基本的な考え方を示しています。必要に応じて実行できます。

于 2012-07-14T18:27:03.757 に答える