親,我的簡書已不再維護和更新了,所有文章都遷移到了我的個人博客:https://mikefighting.github.io/,歡迎交流。
刮獎是商家類項目中經常使用的組件,其實現方式也有多種,下面介紹一種使用Core Graphics實現的一種方式。
Core Graphics中有一種根據遮罩圖片(Masking Images)和原圖片最終合成位圖的方法,下面看一個官方文檔給出的效果來一個直觀的展示。
原圖
遮罩圖
合成圖
從中可以看到黑色的部分將原圖顯示了出來,白色的部分把原圖遮住了,灰色的部分和原圖經過一定的算法進行了合成。我們可以通過不斷的改變遮罩層中某部分的顏色,最終產生刮獎的效果。具體步驟如下:
實現步驟
從中可以看出,剛開始產生的Marsk是黑色的,這時合成之后蒙層圖片原樣展示,手指一動的時候往mask上繪制了白色的線條,這樣,合成之后蒙層上被劃過的地方被白色所取代,這樣就出現了刮獎的效果,在每次繪制完成之后只需要調用
setNeedsDisplay
方法,然后在drawRect
方法中不斷展現最終合成的圖片即可。具體的代碼如下:
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
float scale = [UIScreen mainScreen].scale;
//1. 獲取刮獎層
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手指滑動時不斷在這個context上畫上白線。
contextMask = CGBitmapContextCreate(CFDataGetMutableBytePtr(pixels), imageWidth, imageHeight , 8, imageWidth, colorspace, kCGImageAlphaNone);
CGContextFillRect(contextMask, self.frame);
// 設置滑動時候產生的線條顏色是白色
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. 根據iamge mask產生最終的圖片
scratchImage = CGImageCreateWithMask(hideImage, mask);
CGImageRelease(mask);
CGColorSpaceRelease(colorspace);
手指滑動時候調用的方法:
- (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);
// 調用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)];
}