1.前言
之前需求有个刮一刮出答案的功能,做个记录,希望对需要的同学有帮助。
实现原理
给展示的view添加CAShapeLayer的mask,当我们滑动的时候,把轨迹添加到path上,添加的地方就可以显示出来。
不太懂mask的同学可以看ios CALayer之mask使用。
2.实现方法
实现方法如下
2.1初始化
@interface LayerScrapeView()
@property (nonatomic, strong) UIImageView *scrapeMaskView;
@property (nonatomic, strong) UIView *scrapeContentView;
@property (nonatomic, strong) CAShapeLayer *maskLayer;
@property (nonatomic, strong) UIBezierPath *maskPath;
@end
- (instancetype)initWithFrame:(CGRect)frame
contentView:(UIView *)contentView
maskView:(UIImageView *)maskView{
self = [super initWithFrame:frame];
if(self){
self.scrapeMaskView = maskView;
[self addSubview:maskView];
self.scrapeContentView = contentView;
[self addSubview:contentView];
self.maskLayer = [CAShapeLayer layer];
self.maskLayer.strokeColor = [UIColor whiteColor].CGColor;
// self.maskLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:0].CGColor;
self.maskLayer.lineWidth = 20;
self.maskLayer.frame = contentView.bounds;
self.maskLayer.lineCap = kCALineCapRound;
self.scrapeContentView.layer.mask = self.maskLayer;
self.maskPath = [UIBezierPath bezierPath];
}
return self;
}
2.2移动添加path
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint point = [touch locationInView:self.scrapeContentView];
[self.maskPath addLineToPoint:point];
[self.maskPath moveToPoint:point];
self.maskLayer.path = self.maskPath.CGPath;
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UIGraphicsBeginImageContextWithOptions(self.scrapeContentView.bounds.size, NO, [UIScreen mainScreen].scale);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.scrapeContentView.layer renderInContext:context];
UIImage *image= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGFloat percent = 1 - [self pixelPercentWithImage:image];
if(percent < 0.75) return ;//超过0.75则不用滑动
[self showContentView];
self.userInteractionEnabled = NO;
}
2.3计算透明占比
截图然后计算图片透明像素占比
- (CGFloat)pixelPercentWithImage:(UIImage *)image{
NSInteger alphaCount = 0;
CGImageRef imageRef = [image CGImage];
size_t imageWidth = CGImageGetWidth(imageRef);
size_t imageHeight = CGImageGetHeight(imageRef);
size_t bytesPerRow = imageWidth * 4;
uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), imageRef);
size_t pixelNum = imageWidth * imageHeight;
uint32_t* pCurPtr = rgbImageBuf;
for (int i = 0; i < pixelNum; i++, pCurPtr++){
uint8_t *ptr = (uint8_t *)pCurPtr;
if(ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0)alphaCount++; //透明颜色
}
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(rgbImageBuf);
return alphaCount*1.0/pixelNum;
}
3.补充
这里也有一种比较生硬的方式
-(void)touchesMoved:(NSSet<UITouch *>* )touches withEvent:(UIEvent* )event {
UITouch * touch = touches.anyObject;
CGPoint contentPoint = [touch locationInView:self.scrapeMaskView];
CGRect rect = CGRectMake(contentPoint.x, contentPoint.y, 30, 30);
UIGraphicsBeginImageContextWithOptions(self.scrapeMaskView.bounds.size, NO, [UIScreen mainScreen].scale);
CGContextRef ref = UIGraphicsGetCurrentContext();
[self.scrapeMaskView.layer renderInContext:ref];
CGContextClearRect(ref, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.scrapeMaskView.image = image;
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// UIImageWriteToSavedPhotosAlbum(self.scrapeMaskView.image, self, @selector(savedPhotoImage:savingWithError:contextInfo:), nil);
CGFloat percent = [self pixelPercentWithImage:self.scrapeMaskView.image];
NSLog(@"-----------%f",percent);
}
这种也可以实现,但是流畅度比较差,另外计算像素透明度会有很大的偏差。