先看下效果圖
預覽.gif
項目里需要做個刮刮卡功能,網上簡單搜了一下臭胜,基本都是采用清除圖層的方式來實現(xiàn):
如下所示:
// 觸摸任意位置
UITouch *touch = touches.anyObject;
// 觸摸位置在圖片上的坐標
CGPoint cententPoint = [touch locationInView:self.imageView];
// 設置清除點的大小
CGRect rect = CGRectMake(cententPoint.x, cententPoint.y, 20, 20);
// 默認是去創(chuàng)建一個透明的視圖
UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, 0);
// 獲取上下文(畫板)
CGContextRef ref = UIGraphicsGetCurrentContext();
// 把imageView的layer映射到上下文中
[self.imageView.layer renderInContext:ref];
// 清除劃過的區(qū)域
CGContextClearRect(ref, rect);
// 獲取圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 結束圖片的畫板, (意味著圖片在上下文中消失)
UIGraphicsEndImageContext();
self.imageView.image = image;
如果粗略使用沒什么問題莫其,但是一旦快速滑動的過程浇揩,劃痕就非常難看。而且由于每次采用繪制圖片的方式憨颠,比較消耗性能胳徽。
本人也嘗試過優(yōu)化劃痕形狀,或者修改繪制方式爽彤,始終不理想养盗。
解決方案:
后來采用mask+UIBezierPath的方案來實現(xiàn)。(對于layer的mask不理解的同學可以去簡單看下mask的原理)
就是把刮刮卡的思路反過來适篙,原本是把遮蓋層劃掉爪瓜,反過來也可以直接將目標圖層劃出來。這種做法就是遮蓋界面在下層匙瘪,獎勵界面在上層铆铆。剛好和常識相反。
創(chuàng)建maskLayer
- (CAShapeLayer *)maskLayer{
if(!_maskLayer) {
_maskLayer = [CAShapeLayer layer];
_maskLayer.lineCap = kCALineCapRound;
_maskLayer.lineWidth = self.ScratchSize;
_maskLayer.strokeColor = [UIColor blackColor].CGColor;
}
return _maskLayer;
}
將maskLayer作為獎品界面的mask
self.prizeView.layer.mask = self.maskLayer;
然后在手勢劃過的地方丹喻,繪制線條(劃痕)薄货,將路徑傳遞給maskLayer。
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = touches.anyObject;
CGPoint prePoint = [touch previousLocationInView:self.prizeView];
CGPoint currentPoint = [touch locationInView:self.prizeView];
[self.maskPath moveToPoint:prePoint];
[self.maskPath addLineToPoint:currentPoint];
self.maskLayer.path = self.maskPath.CGPath;
}