Mask动画深入学习

作者: 怪小喵 | 来源:发表于2016-07-20 23:24 被阅读549次

    请下载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

    相关文章

      网友评论

      • DecadentOrMagic:请教一下,在哪个滑动解锁哪里,为什么要用self.unlock = unlock,不写这句为什么出现不了最后的效果?

      本文标题:Mask动画深入学习

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