Mask動(dòng)畫深入學(xué)習(xí)

請(qǐng)下載Demo

CALayer有一個(gè)屬性叫做mask(對(duì)應(yīng)UIView中maskView屬性,下文說(shuō)的maskView和mask是一個(gè)東西)mask圖層定義了父圖層的部分可見(jiàn)區(qū)域,功能類似于PS 中的圖層蒙版。
mask圖層的Color屬性是無(wú)關(guān)緊要的,真正重要的是圖層的輪廓。mask屬性就像是一個(gè)餅干切割機(jī),mask圖層實(shí)心的部分會(huì)被保留下來(lái),其他的則會(huì)被拋棄。(如圖1.1)。

也可以這樣理解,maskView將每個(gè)point的alpha賦值給View的重疊部分相對(duì)應(yīng)的point,這樣view的重疊每個(gè)point都有個(gè)alpha值了,view重疊部分就可能顯示多種透明色。

就如圖1.1 而言,由于maskView顏色的alpha為1.0,那么與view重疊部分的alpha也應(yīng)該為1.0(即重疊部分沒(méi)變化),與mask顏色沒(méi)關(guān)系。

圖1.1

還是云里霧里的也沒(méi)關(guān)系。您可以下載demo對(duì)照學(xué)習(xí),注釋非常詳細(xì),一看就懂。
demo中前三個(gè)例子可有幫助更深刻的體會(huì)mask屬性的基本原理。


CALayer蒙板圖層真正厲害的地方在于蒙板圖不局限于靜態(tài)圖。任何有圖層構(gòu)成的都可以作為mask屬性,這意味著你的蒙板可以通過(guò)代碼甚至是動(dòng)畫實(shí)時(shí)生成。

  • 利用maskView實(shí)現(xiàn)圖片漸變切換動(dòng)畫

如圖1.2 的圖片切換效果,其實(shí)是使用了的alpha通道變化的maskView完成圖片的切換。


圖1.2
    // 在底層的 圖片 background(最后要顯示出來(lái))
    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 由兩個(gè)分別加載 “mask1” “mask” 的imageView拼接而成。加在 上層圖片上 , 注意 兩張透明度漸變的圖片是重點(diǎn)。是它們使 上層圖片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];
    
    
    // 兩個(gè)imageView的動(dòng)畫 使maskView的alpha通道由 1 變成 0 ,導(dǎo)致 上層圖片消失, 達(dá)到切換的效果
    [UIView animateWithDuration:2.f delay:2.f options:0 animations:^{
        picOne.y -= 400;
        picTwo.y += 400;
    } completion:^(BOOL finished) {
        
    }];
  • maskView配合CAGradientLayer使用

這個(gè)例子實(shí)現(xiàn)了 iPhone的滑動(dòng)解鎖效果

1.首先構(gòu)建一個(gè) 顏色漸變的layer,可以使用CAGradientLayer這個(gè)類,你也可以像上一個(gè)例子一樣使用圖片,看起來(lái)像圖1.3.1就行。
關(guān)于CAGradientLayer的屬性詳細(xì)解析可參考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.讓這個(gè)圖層動(dòng)起來(lái),加個(gè)動(dòng)畫。

  // CAGradientLayer可用來(lái)處理顏色漸變,它的漸變色也可以做隱式動(dòng)畫
   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的遮罩,完成。

   // 設(shè)置 gradientLayer  的 mask 為 unLock   有透明度的地方 就露出來(lái)了
    UILabel *unlock = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
    self.unlock = unlock;
    unlock.alpha = 0.5;
    unlock.text = @"滑動(dòng)來(lái)解鎖 >>";
    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];
   
    
    
    // 創(chuàng)建mask
    // 貝塞爾曲線(創(chuàng)建一個(gè)圓)
    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;
    
    
    
    // 創(chuàng)建覆蓋在最底層imageView上的模糊圖片, 添加mask   注意mask為一個(gè)圓形(模糊圖片只會(huì)顯示一個(gè)圓,其他地方會(huì)變成透明)
    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];
    
    // 關(guān)閉CoreAnimation實(shí)時(shí)動(dòng)畫繪制(核心)
    [CATransaction setDisableActions:YES];
    _maskLayer.position = recognizer.view.center;
}
  • 毛玻璃漸變效果

如圖1.5.1 效果 ,如果你理解了mask的原理,這個(gè)和上一個(gè)類似,
在圖片層上 加一層毛玻璃層,在毛玻璃層上加一層透明度漸變的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  全透過(guò)  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);

以上例子的代碼可以在這下載
另外推薦一個(gè)mask實(shí)現(xiàn)的動(dòng)畫效果,mask的實(shí)現(xiàn)方式非常巧妙。
https://github.com/andreamazz/BubbleTransition

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容