利用Core Graphics實(shí)現(xiàn)刮獎(jiǎng)效果

親,我的簡(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)];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個(gè)像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,772評(píng)論 0 7
  • 卷首語(yǔ) 歡迎來(lái)到 objc.io 的第三期! 這一期都是關(guān)于視圖層的。當(dāng)然視圖層有很多方面,我們需要把它們縮小到幾...
    評(píng)評(píng)分分閱讀 1,932評(píng)論 0 18
  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,722評(píng)論 0 20
  • 遲宇宙說(shuō):“擁有生活的意境,即或不掌握足夠的財(cái)富和權(quán)力,也活得自由、豐富、飽滿”,內(nèi)心“純凈、浪漫、柔軟,有一片小...
    愛(ài)君如初閱讀 515評(píng)論 0 0
  • 我已經(jīng)忘了上回失眠是什么時(shí)候了,可能是青春期時(shí)候的通宵玩樂(lè),那并不能稱為真正的失眠吧。 今天晚上我失眠了。 我晚上...
    kiwi大妞妞閱讀 358評(píng)論 0 1

友情鏈接更多精彩內(nèi)容