Mask动画深入学习

请下载Demo

CALayer有一个属性叫做mask(对应UIView中maskView属性,下文说的maskView和mask是一个东西)mask图层定义了父图层的部分可见区域,功能类似于PS 中的图层蒙版。
mask图层的Color属性是无关紧要的,真正重要的是图层的轮廓。mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃。(如图1.1)。

也可以这样理解,maskView将每个point的alpha赋值给View的重叠部分相对应的point,这样view的重叠每个point都有个alpha值了,view重叠部分就可能显示多种透明色

就如图1.1 而言,由于maskView颜色的alpha为1.0,那么与view重叠部分的alpha也应该为1.0(即重叠部分没变化),与mask颜色没关系。

图1.1

还是云里雾里的也没关系。您可以下载demo对照学习,注释非常详细,一看就懂。
demo中前三个例子可有帮助更深刻的体会mask属性的基本原理。


CALayer蒙板图层真正厉害的地方在于蒙板图不局限于静态图。任何有图层构成的都可以作为mask属性,这意味着你的蒙板可以通过代码甚至是动画实时生成。

  • 利用maskView实现图片渐变切换动画

如图1.2 的图片切换效果,其实是使用了的alpha通道变化的maskView完成图片的切换。


图1.2
    // 在底层的 图片 background(最后要显示出来)
    UIImageView *background = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    background.image        = [UIImage imageNamed:@"base"];
    background.center       = self.view.center;
    [self.view addSubview:background];
    
    // 在上层的 图片 upGround
    UIImageView *upGround = [[UIImageView alloc] initWithFrame:background.frame];
    upGround.image        = [UIImage imageNamed:@"background"];
    [self.view addSubview:upGround];
    
    
    // maskView 由两个分别加载 “mask1” “mask” 的imageView拼接而成。加在 上层图片上 , 注意 两张透明度渐变的图片是重点。是它们使 上层图片upGround 显示 或者隐藏
    UIView *mask      = [[UIView alloc] initWithFrame:upGround.bounds];
    upGround.maskView = mask;
    
    UIImageView *picOne = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 400)];
    picOne.image        = [UIImage imageNamed:@"mask1"];
    [mask addSubview:picOne];
    
    UIImageView *picTwo = [[UIImageView alloc] initWithFrame:CGRectMake(100, -200, 100, 400)];
    picTwo.image        = [UIImage imageNamed:@"mask"];
    [mask addSubview:picTwo];
    
    
    // 两个imageView的动画 使maskView的alpha通道由 1 变成 0 ,导致 上层图片消失, 达到切换的效果
    [UIView animateWithDuration:2.f delay:2.f options:0 animations:^{
        picOne.y -= 400;
        picTwo.y += 400;
    } completion:^(BOOL finished) {
        
    }];
  • maskView配合CAGradientLayer使用

这个例子实现了 iPhone的滑动解锁效果

1.首先构建一个 颜色渐变的layer,可以使用CAGradientLayer这个类,你也可以像上一个例子一样使用图片,看起来像图1.3.1就行。
关于CAGradientLayer的属性详细解析可参考CAGradientLayer的一些属性解析

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    [self.view.layer addSublayer:gradientLayer];
    gradientLayer.frame = CGRectMake(0, 200, self.view.width, 64);
    gradientLayer.colors = @[
                             (__bridge id)[UIColor blackColor].CGColor,
                             (__bridge id)[UIColor whiteColor].CGColor,
                             (__bridge id)[UIColor blackColor].CGColor,
                             ];
    gradientLayer.locations = @[@0.25,@0.5,@0.75];
    gradientLayer.startPoint = CGPointMake(0, 0.5);
    gradientLayer.endPoint = CGPointMake(1, 0.5);
图1.3.1

2.让这个图层动起来,加个动画。

  // CAGradientLayer可用来处理颜色渐变,它的渐变色也可以做隐式动画
   CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"locations"];
   basicAnimation.fromValue = @[@0, @0, @0.25];
   basicAnimation.toValue = @[@0.75, @1, @1];
   basicAnimation.duration = 2.5;
   basicAnimation.repeatCount = HUGE;
   [gradientLayer addAnimation:basicAnimation forKey:nil];
图1.3.2

3.让UILabel上的文字成为CAGradientLayer的遮罩,完成。

   // 设置 gradientLayer  的 mask 为 unLock   有透明度的地方 就露出来了
    UILabel *unlock = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
    self.unlock = unlock;
    unlock.alpha = 0.5;
    unlock.text = @"滑动来解锁 >>";
    unlock.textAlignment = NSTextAlignmentCenter;
    unlock.font = [UIFont boldSystemFontOfSize:30];
    gradientLayer.mask = unlock.layer;
图1.3.3
  • maskView配合CAShapeLayer使用

直接上代码,在图片层上 加一层毛玻璃层,在毛玻璃层上加一层圆形的mask。

图1.4.1
    // 最底层的view  显示图片
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
    imageView.image = [UIImage imageNamed:@"Slice"];
    [self.view addSubview:imageView];
   
    
    
    // 创建mask
    // 贝塞尔曲线(创建一个圆)
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0)
                                                        radius:100
                                                    startAngle:DEGREES(0)
                                                      endAngle:DEGREES(360)
                                                     clockwise:YES];

    _maskLayer = [CAShapeLayer layer];
    _maskLayer.path     = path.CGPath;
    _maskLayer.position = CGPointMake(_showView.bounds.size.width/2.f,
                                      _showView.bounds.size.height/2.f);
    _maskLayer.fillColor = [UIColor whiteColor].CGColor;
    _maskLayer.position = self.view.center;
    
    
    
    // 创建覆盖在最底层imageView上的模糊图片, 添加mask   注意mask为一个圆形(模糊图片只会显示一个圆,其他地方会变成透明)
    UIView *blurView = [[UIView alloc] initWithFrame:self.view.bounds];
    blurView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:blurView];
    blurView.layer.mask = _maskLayer;
    blurView.layer.contents = (__bridge id)([[UIImage imageNamed:@"Slice"] imgWithBlur].CGImage);
    
    
    
    /*
     透明的View,用于maskView中的ShapeLayer的参考View(用于拖拽)
     */
    _showView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    _showView.backgroundColor = [UIColor clearColor];
    _showView.center = self.view.center;
    [self.view addSubview:_showView];
    
    UIPanGestureRecognizer *recognizer =
    [[UIPanGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(handlePan:)];
    [_showView addGestureRecognizer:recognizer];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    // 拖拽
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    
    // 关闭CoreAnimation实时动画绘制(核心)
    [CATransaction setDisableActions:YES];
    _maskLayer.position = recognizer.view.center;
}
  • 毛玻璃渐变效果

如图1.5.1 效果 ,如果你理解了mask的原理,这个和上一个类似,
在图片层上 加一层毛玻璃层,在毛玻璃层上加一层透明度渐变的mask,OK。


图1.5.1


  UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
    imageView.image = [UIImage imageNamed:@"Slice"];
    [self.view addSubview:imageView];
    
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    [self.view.layer addSublayer:gradientLayer];
    gradientLayer.frame = self.view.bounds;
    // 颜色的透明度   alpha   0.0  全透过  1.0 不透明
    gradientLayer.colors = @[
                             (__bridge id)[UIColor colorWithWhite:1 alpha:0.0].CGColor,
                             (__bridge id)[UIColor colorWithWhite:1 alpha:1.0].CGColor,
                             ];
    gradientLayer.locations = @[@0.35,@0.55];
    _gradientLayer = gradientLayer;
    
    UIView *blurView = [[UIView alloc] initWithFrame:self.view.bounds];
    blurView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:blurView];
    blurView.layer.mask = gradientLayer;
    blurView.layer.contents = (__bridge id)([[UIImage imageNamed:@"Slice"] imgWithBlur].CGImage);

以上例子的代码可以在这下载
另外推荐一个mask实现的动画效果,mask的实现方式非常巧妙。
https://github.com/andreamazz/BubbleTransition

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容