Scrach Off Effect (Erasing layer)

Problem: I had to develop a demo app for a lottery ticket. It had to have a scratch off part, where user will scratch off a top layer to see if he had won anything.

Description: No description for you 🙂 Problem is quite obvious.

Solution:

I’ve created a view (I’ve called it ScratchView) that has a UIImageView on it. UIImageView is stretched across the whole view, but if you wanna you can pick your own width and height. Background of my view is set to clear color and I’ve painted my UIImageView with black color. Here’s the code that does it:

- (id)initWithFrame:(CGRect)frame

{

self = [super initWithFrame:frame];

if (self)

{

self.backgroundColor = [UIColor clearColor];

scratchField = [[UIImageView alloc] initWithFrame:self.bounds];

scratchField.backgroundColor = [UIColor clearColor];

[self addSubview:scratchField];

//overlay scratchField with black layer (rectagle)

[scratchField.image drawInRect:scratchField.bounds];

CGSize size;

size.height = scratchField.bounds.size.height;

size.width = scratchField.bounds.size.width;

UIGraphicsBeginImageContext(size);

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetRGBFillColor(context, 0.96, 0.35, 0.0, 1.0);

CGContextFillRect(context, scratchField.bounds);

scratchField.image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

}

return self;

}

Just to point out, self, in this context is a view (ScratchView). It’s not a view controller, just a plain view.

Next thing I had to do is create a scratch of effect. It wasn’t that hard after I discovered one life saving line of code 🙂 But lets start from beginning. To create a scratch off effect i had to delete color (set color to clear) on my UIImageView. So what I did is I used touchesBegan and touchesMoved actions. On touchesBegan I just took start point of users touch. And in touchesMoved I’m erasing a line (or a curve if you wish) from users start point to current point. At the end I copy current point to users start point and if user continues to move just repeat the same method. Think that code is self explanatory but I wanna point out the money winning line of code. It’s this one:


CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

You can set blending mode to clear and what that does is exactly what I was looking for. It doesn’t paint on your UIImageView, it sets it to clear. So where ever you move your finger it will set that path to clear. Here’s the rest of the code.


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

UITouch *touch = [touches anyObject];

if ([touch tapCount] == 2)

{

//taped 2 time

return;

}

userPoint = [touch locationInView:scratchField];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

UITouch *touch = [touches anyObject];

CGPoint currentPoint = [touch locationInView:scratchField];

UIGraphicsBeginImageContext(scratchField.frame.size);

[scratchField.image drawInRect:scratchField.bounds];

CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); //kCGLineCapSquare, kCGLineCapButt, kCGLineCapRound

CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 25.0); // for size

CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0); //values for R, G, B, and Alpha

CGContextBeginPath(UIGraphicsGetCurrentContext());

CGContextMoveToPoint(UIGraphicsGetCurrentContext(), userPoint.x, userPoint.y);

CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);

CGContextStrokePath(UIGraphicsGetCurrentContext());

scratchField.image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

userPoint = currentPoint;

}

Hope this helps. You can find a full project here (btw: there is a view controller called ScratchTiceketViewController. Just ignore it. It was my test view controller and I’m to lazy to remove it :))

http://www.4shared.com/file/j1g6ieI5/TestingScratchTicketEffekt.html

All comments are welcomed. I publish all my blog notifications on my twitter so if you wanna you can follow me @ http://twitter.com/PavlovicMario

About buildingmyworld

Will fill this part later. Captain procrastinator mode is currently on!
This entry was posted in iOS Development, Objective-c, xcode and tagged , , , , , , , , . Bookmark the permalink.

12 Responses to Scrach Off Effect (Erasing layer)

  1. Fadi says:

    Excellent post! just what i was searching for. One question, is there is way to know when the complete view is scratched successfully?

  2. I was trying to implement that but couldn’t find a way.. If you do, please post it here..

  3. Evris says:

    Excellent article! Have you tried the opposite, or do you thing that could be done?

    I mean that having an image on top , for example a pic with holes (png so to be transparent) and with touch to draw on a second layer bellow image and only there!

    So we have the effect of fill in the gaps

  4. Anonymous says:

    Where did you defined userPoint ??? in your .h? what type is it?

  5. RJ says:

    I think userPoint is a CGPoint

    In Interface:
    @property CGPoint userPoint;

    In implementation:
    @synthesize userPoint;

  6. wiralim says:

    Thanks…
    You’ve shared your work and that help me doing my project which i working right now…
    Thank u…

  7. wiralim says:

    Hi Mario Pavlovic,
    Thanks for this tutorial, but i got a problem. what i want to do is describe below :
    Can you change the “alpha” value wherever the user scratch on the iPhone screen ? then if the user scratch more and more on the screen, the image on the background will be clearer and clearer, finally the image is reveal.

    do you have any solution to do that ?

  8. jason says:

    Hello, the link for the source is dead. Can you please update it. Thank you.

  9. herstik says:

    yeah please update link… I’m looking for the same… cheers

  10. Tony says:

    Any chance to provide a new download link? Thanks!

  11. Anonymous says:

    your the best

Leave a comment