親,我的簡(jiǎn)書已不再維護(hù)和更新了,所有文章都遷移到了我的個(gè)人博客:https://mikefighting.github.io/,歡迎交流。
刮獎(jiǎng)是商家類項(xiàng)目中經(jīng)常使用的組件,其實(shí)現(xiàn)方式也有多種,下面介紹一種使用Core Graphics實(shí)現(xiàn)的一種方式。
Core Graphics中有一種根據(jù)遮罩圖片(Masking Images)和原圖片最終合成位圖的方法,下面看一個(gè)官方文檔給出的效果來(lái)一個(gè)直觀的展示。

原圖

遮罩圖

合成圖
從中可以看到黑色的部分將原圖顯示了出來(lái),白色的部分把原圖遮住了,灰色的部分和原圖經(jīng)過(guò)一定的算法進(jìn)行了合成。我們可以通過(guò)不斷的改變遮罩層中某部分的顏色,最終產(chǎn)生刮獎(jiǎng)的效果。具體步驟如下:

實(shí)現(xiàn)步驟
從中可以看出,剛開(kāi)始產(chǎn)生的Marsk是黑色的,這時(shí)合成之后蒙層圖片原樣展示,手指一動(dòng)的時(shí)候往mask上繪制了白色的線條,這樣,合成之后蒙層上被劃過(guò)的地方被白色所取代,這樣就出現(xiàn)了刮獎(jiǎng)的效果,在每次繪制完成之后只需要調(diào)用
setNeedsDisplay方法,然后在drawRect方法中不斷展現(xiàn)最終合成的圖片即可。具體的代碼如下:
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
float scale = [UIScreen mainScreen].scale;
//1. 獲取刮獎(jiǎng)層
UIGraphicsBeginImageContextWithOptions(hideView.bounds.size, NO, 0);
[hideView.layer renderInContext:UIGraphicsGetCurrentContext()];
hideView.layer.contentsScale = scale;
hideImage = UIGraphicsGetImageFromCurrentImageContext().CGImage;
UIGraphicsEndImageContext();
size_t imageWidth = CGImageGetWidth(hideImage);
size_t imageHeight = CGImageGetHeight(hideImage);
CFMutableDataRef pixels = CFDataCreateMutable(NULL, imageWidth * imageHeight);
//2. 獲取context手指滑動(dòng)時(shí)不斷在這個(gè)context上畫上白線。
contextMask = CGBitmapContextCreate(CFDataGetMutableBytePtr(pixels), imageWidth, imageHeight , 8, imageWidth, colorspace, kCGImageAlphaNone);
CGContextFillRect(contextMask, self.frame);
// 設(shè)置滑動(dòng)時(shí)候產(chǎn)生的線條顏色是白色
CGContextSetStrokeColorWithColor(contextMask, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(contextMask, _sizeBrush);
CGContextSetLineCap(contextMask, kCGLineCapRound);
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(pixels);
CGImageRef mask = CGImageMaskCreate(imageWidth, imageHeight, 8, 8, imageWidth, dataProvider, nil, NO);
//2. 根據(jù)iamge mask產(chǎn)生最終的圖片
scratchImage = CGImageCreateWithMask(hideImage, mask);
CGImageRelease(mask);
CGColorSpaceRelease(colorspace);
手指滑動(dòng)時(shí)候調(diào)用的方法:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
UITouch *touch = [[event touchesForView:self] anyObject];
currentTouchLocation = [touch locationInView:self];
previousTouchLocation = [touch previousLocationInView:self];
[self scratchTheViewFrom:previousTouchLocation to:currentTouchLocation];
}
// 繪制圖像
- (void)scratchTheViewFrom:(CGPoint)startPoint to:(CGPoint)endPoint {
BOOL needRender = [self needRenderWithCurrentLocation:endPoint previousLocation:previousTouchLocation];
if (!needRender) return;
float scale = [UIScreen mainScreen].scale;
CGContextMoveToPoint(contextMask, startPoint.x * scale, (self.frame.size.height - startPoint.y) * scale);
CGContextAddLineToPoint(contextMask, endPoint.x * scale, (self.frame.size.height - endPoint.y) * scale);
CGContextStrokePath(contextMask);
// 調(diào)用drawRect 方法
[self setNeedsDisplay];
self.isDrawn = YES;
}
- (void)drawRect:(CGRect)rect {
UIImage *imageToDraw = [UIImage imageWithCGImage:scratchImage];
[imageToDraw drawInRect:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)];
}