美文网首页
layer 之 mask学习

layer 之 mask学习

作者: 充满活力的早晨 | 来源:发表于2018-10-09 19:59 被阅读55次

为什么对layer 的mask感兴趣呢?这是因为前些天看别人写了个刮刮乐的demo,就是根据mask属性来设计,因此对该属性想好好研究下。

概述

layer的alpha通道决定了layer 的content和background的显示量。完全或者部分opaque的像素允许底层内容显示,但是完全opaque的像素组织layer的content和background显示。mask属性默认是nil。配置mask时候,我们需要设置mask的大小和位置,以确保layer和mask 对齐。

通过上段概述(对苹果官方文档的翻译),我们知道,layer内容的显示只是通过mask(layer)的alpha来控制。 要是alpha透明,那么layer也就是透明的啦。

如何获取alpha 的透明度

我们知道layer其实就是承载bitmap的容器。我们可以获取到layer的image。然后将该image转换成只有带有alpha通道的bitmap即可。

        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 3);
        CGContextRef  context = UIGraphicsGetCurrentContext();
        [layerMask renderInContext:context];
        UIImage * imageNew = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        CGSize size = image.size;
        int bitmapByteCount  =size.width * size.height;
        UInt8 * dataN = malloc(bitmapByteCount*sizeof(UInt8));
        context = CGBitmapContextCreate(dataN, size.width, size.height, 8, size.width, CGColorSpaceCreateDeviceGray(), kCGImageAlphaOnly);
        CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));
        
        CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image.CGImage);
        int width = size.width;
        int heigt = size.height;
        
        for (int x = 0; x<width; x++) {
            for (int y=0; y<heigt; y++) {
                float alpha =dataN[width*x+y];
                NSLog(@ "第%d row  %d  height %f",x,y,alpha);
            }
        }

这里没有直接对image进行分析,而是将其重新绘制成image,在对image进行分析。原因是直接分析layer的image,改image可能进行压缩,延展了。不好分析。

其实我们刚创建的layer,在第一次渲染的的时候,系统是会给我们创建一个bitmap图。这个图的content是完全透明的。因此我们要是用一个不添加新的contens的新建layer当做mask,那么,layer将是完全透明的。不会显示任何元素。

简单demo

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIImage * image =[UIImage imageNamed:@"123"];
        CALayer * layerMask = [CALayer layer];
        layerMask.bounds =self.bounds;
        layerMask.position= self.center;
        layerMask.contents =(__bridge id _Nullable)(image.CGImage);
        
        CALayer * layer = [CALayer layer];
        layer.bounds = self.bounds;
        layer.position= self.center;
        layer.backgroundColor =[UIColor redColor].CGColor;
        layer.mask = layerMask;
        [self.layer addSublayer:layer];

    }
    return self;
}
123.png

显示结果


具体分析

我们知道mask是一个layer ,那么就有positon 和size,我们看看要是改变positon和size ,会有啥效果。

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIImage * image =[UIImage imageNamed:@"123"];
        CALayer * layerMask = [CALayer layer];
        layerMask.bounds =CGRectMake(0, 0, 100, 100);
        layerMask.position= self.center;
        layerMask.contents =(__bridge id _Nullable)(image.CGImage);
        
        CALayer * layer = [CALayer layer];
        layer.bounds = self.bounds;
        layer.position= self.center;
        layer.backgroundColor =[UIColor redColor].CGColor;
        layer.mask = layerMask;
        [self.layer addSublayer:layer];

    }
    return self;
}
image.png

mask的大小要是比layer小,那么超出mask区域的layer部分不显示。相当于切掉了

对mask进行下列更改

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIImage * image =[UIImage imageNamed:@"123"];
        CALayer * layerMask = [CALayer layer];
        layerMask.bounds =CGRectMake(0, 0, 100, 100);
        layerMask.position= self.center;
        layerMask.contents =(__bridge id _Nullable)(image.CGImage);
        layerMask.cornerRadius = 50;
        layerMask.masksToBounds = YES;
        
        CALayer * layer = [CALayer layer];
        layer.bounds = self.bounds;
        layer.position= self.center;
        layer.backgroundColor =[UIColor redColor].CGColor;
        layer.mask = layerMask;
        [self.layer addSublayer:layer];

    }
    return self;
}
image.png

我们知道mask的作用主要是控制layer的显示区域,那么,我们利用此特性可以对layer进行区域显示的动画操作

#import "LayerMask.h"
@interface LayerMask()
@property (nonatomic, strong) CADisplayLink *link;
@property (nonatomic, strong) CAShapeLayer *circleMask;

@end
@implementation LayerMask

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor redColor];
        //创建一个CAShapeLayer作为MaskLayer
        self.circleMask = [CAShapeLayer layer];
        self.circleMask.position = self.center;
        self.circleMask.bounds = self.bounds;
        //设置路径
         self.circleMask.path      = [UIBezierPath bezierPathWithArcCenter:self.center radius:20 startAngle:0 endAngle:2 * M_PI clockwise:YES].CGPath;
        self.circleMask.lineWidth = 5;
        self.circleMask.fillRule  = kCAFillRuleEvenOdd;
        self.layer.mask = self.circleMask;
        //添加计时器
        self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(action)];
        [self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    }
    return self;
}
static int num = 1;
-(void)action{
    num ++;
    self.circleMask.path      = [UIBezierPath bezierPathWithArcCenter:self.center radius:20 + num
                                                  startAngle:0
                                                    endAngle:2 * M_PI                                                clockwise:YES].CGPath;
    if (num > 1000) {
        [self.link invalidate];
    }
}
animation.gif

通过上面的知识,其实我们就可以实现了简单的刮刮乐了。

    UIImageView * imageView = [[UIImageView alloc]initWithFrame: [UIScreen mainScreen].bounds];
    imageView.image = [UIImage imageNamed:@"guaguale.jpg"];
    [self.view addSubview:imageView];
    GGView * VC =[[GGView alloc]initWithFrame:CGRectMake(30, 340, 360, 380)];
    VC.backgroundColor = UIColor.grayColor;
    [self.view addSubview:VC];
@interface GGView()
@property (nonatomic,strong) UIBezierPath * panPath;
@property (nonatomic,strong) CAShapeLayer *layerMask;
@end

@implementation GGView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CAShapeLayer * layer = [CAShapeLayer layer];
        self.layerMask= layer;
        self.layer.mask = layer;
        self.panPath = [UIBezierPath bezierPath];
        layer.strokeColor = UIColor.yellowColor.CGColor;
        layer.lineCap = kCALineCapRound;
        layer.lineWidth = 20;
        UIPanGestureRecognizer * panGet = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [self addGestureRecognizer:panGet];
    }
    return self;
}
-(void)pan:(UIPanGestureRecognizer *)pan{
    CGPoint point = [pan locationInView:self];
    if (pan.state ==UIGestureRecognizerStateBegan) {
        [self.panPath moveToPoint:point];
    }
    if (pan.state == UIGestureRecognizerStateChanged) {
        [self.panPath addLineToPoint:point];
        [self.panPath moveToPoint:point];
        self.layerMask.path = self.panPath.CGPath;
        [self caclue];
    }
}

-(void)drawRect:(CGRect)rect{
    
}
-(void)caclue{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 3);
    CGContextRef  context = UIGraphicsGetCurrentContext();
    [self.layer renderInContext:context];
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGSize size = image.size;
//    NSLog(@"%@",NSStringFromCGSize(size));
    int bitmapByteCount  =size.width * size.height;
    UInt8 * data = malloc(bitmapByteCount*sizeof(UInt8));
    context = CGBitmapContextCreate(data, size.width, size.height, 8, size.width, CGColorSpaceCreateDeviceGray(), kCGImageAlphaOnly);
    CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));

    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image.CGImage);
    int width = size.width;
    int mm  =0;
    for (int x = 0; x<size.width; x++) {
        for (int y=0; y<size.height; y++) {
            if (data[y*width+x]==0) {
                mm++;
            }
        }
    }

    float ss = mm*1.0/bitmapByteCount;
    if (ss<0.5) {
        self.layer.mask = nil;
    }
}
@end
刮刮乐

官方文档

相关文章

网友评论

      本文标题:layer 之 mask学习

      本文链接:https://www.haomeiwen.com/subject/dcrjaftx.html