maskView使用進階(配合CAGradientLayer,CAShapeLayer使用)

上一篇文章介紹了maskView的原理和基本使用
接下來介紹下maskView的進階使用

一.利用maskView使用多種圖片做漸變切換動畫

1.素材

base

background

mask

mask1
    // 上述素材按照順序分別是‘base’,'background',''mask','mask1';
    self.view.backgroundColor = [UIColor whiteColor];
    UIImageView *baseGround = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    baseGround.image        = [UIImage imageNamed:@"base"];
    baseGround.center       = self.view.center;
    [self.view addSubview: baseGround];
    
    
    UIImageView *upGround = [[UIImageView alloc] initWithFrame:baseGround.frame];
    upGround.image        = [UIImage imageNamed:@"background"];
    [self.view addSubview: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];
    
    [UIView animateWithDuration:5.f delay:5.f options:0 animations:^{
        picOne.y -= 400;
        picTwo.y += 400;
    } completion:^(BOOL finished) {
        
    }];
  • Code原理解析:
    mask默認色為透明(clearColor),如果picOne和picTwo不存在時邪锌,由于mask是透明,切mask又是upGround的maskView赴蝇,則upGround也會透明超埋,即效果圖只會看到baseGround谢澈。在此例中一開始mask有picOne和picTwo兩個子View,且picOne和picTwo顯示在mask上的部分不是透明部分,所以一開始效果圖只會看到backGround.

  • 圖片漸變動畫實現(xiàn)原理:
    隨著picOne和picTwo的上下部分移動,最終的效果是picOne和picTwo顯示在mask上的都是透明部分旧烧,當顯示在mask上的控件透明時,則mask也會透明画髓,那么backGround也會透明掘剪,最終的效果圖就是逐漸看不到backGround,然后顯示baseGround.

運行效果圖

效果圖

二.maskView配合CAGradientLayer使用

iPhone滑動解鎖效果

先來個Demo來解釋下CAGradientLayer吧奈虾,先了解下CAGradientLayer是個啥玩意杖小,

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor grayColor];
    // 漸變Layer
    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];
 }

運行效果圖:

效果圖

CAGradientLayer可用來處理顏色漸變,它的漸變色也可以做隱式動畫

此例用frame設(shè)置了layer的位置愚墓,也可以用position屬性設(shè)置layer的位置

colors 屬性是設(shè)置CAGradientLayer的漸變顏色(此Demo是從黑-->白-->黑)予权。
locations 屬性是相對于 colors 設(shè)置的,此Demo中l(wèi)ocations值的含義是 按顏色漸變方向劃分 浪册,從(0 -> 0.25)部分是黑色扫腺,從(0.25 -> 0.5)部分是黑到白的漸變過程,以此類推0.75的含義村象。

注意

1.CAGradientLayer 默認的漸變方向是從上到下笆环,即垂直方向攒至。

2.colors 是個NSArray類型,只能存對象躁劣,所以需要將CGColor轉(zhuǎn)換一下迫吐,此屬性可設(shè)置多個值(1個,2個账忘,3個等...志膀,都行),此Demo的滑動解鎖效果只需要 兩種 顏色的漸變鳖擒,所以設(shè)置了三個值溉浙,實際值可根據(jù)需求設(shè)置。

3.設(shè)置好 colors 要設(shè)置好與之相對應(yīng)的 locations

4.如果要改變 CAGradientLayer 的漸變方向蒋荚,則要顯式的給 startPointendPoint 兩個屬性賦值戳稽。

如果要改為水平方向,則需要改成

             gradientLayer.startPoint = CGPointMake(0, 0.5);
             gradientLayer.endPoint = CGPointMake(1, 0.5)           

修改之后的效果圖:

效果圖
startPoint期升,endPoint原理解析

既然 CAGradientLayer 可以繪制出漸變顏色的效果惊奇,那自然有顏色漸變的方向,所以這兩個屬性的作用就是設(shè)置顏色漸變的起始點和結(jié)束點播赁,這兩個屬性共同決定了顏色漸變的方向:

原理分析圖


接下來來個CAGradientLayer的動效Demo(只需要在上面的代碼添加幾句即可)

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor grayColor];
    // 漸變Layer
    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];
    
    // 添加部分
    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. 將keyPath賦值為“l(fā)ocations”是讓CAGradientLayer的locations屬性做動畫赊时,因為locations對應(yīng)著顏色,那么顏色也會跟著動行拢,最終的顯示效果就是:
效果圖

疑問:但是如何將顏色漸變的動畫作用在UILabel的文字上呢 祖秒?

1.其實非常簡單,就是讓UILabel上的文字稱為CAGradientLayer的遮罩即可舟奠。

再來修改下代碼

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor grayColor];
    // 漸變Layer
    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];
    
    // 添加部分
    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];
    
    // 第二次添加部分
    UILabel *unlock = [[UILabel alloc] initWithFrame:gradientLayer.bounds];
    // 必需要強引用保存unlock竭缝,此句也可以用[self.view addSubview:unlock]來替代;
    self.unlock = unlock;   
    unlock.alpha = 0.5;
    unlock.text = @"滑動來解鎖 >>";
    unlock.textAlignment = NSTextAlignmentCenter;
    unlock.font = [UIFont boldSystemFontOfSize:30];
    gradientLayer.mask = unlock.layer;
 }
 
 

代碼解析:

1.self.unlock = unlock; 用強引用保存label (@property (nonatomic, strong)UILabel *unlock;) ,防止 label dealloc沼瘫,如果label被銷毀抬纸,則label沒有了delegate。

為什么要強引用 unlock 標簽 ?

當一個控件(UIiew,UIlabel,UIbutton)創(chuàng)建時,系統(tǒng)會自動創(chuàng)建一個與之相對應(yīng)的layer耿戚,layer怎么顯示湿故,實際是與之對應(yīng)的控件相關(guān)的,layer與之對應(yīng)的控件是delegate關(guān)系膜蛔,即layer.delegate=當前控件坛猪,在系統(tǒng)創(chuàng)建layer之后,layer的delegate會執(zhí)行 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context 方法繪制圖層來顯示給用戶看皂股,當控件銷毀了墅茉,則不會執(zhí)行此方法了,那么layer上什么也沒有,又因為控件創(chuàng)建的默認色為clearColor(如果設(shè)置了backgroundColor為不透明就斤,則layer也會不透明),那么layer也會全透明(UIImageView比較特殊悍募,除外)。在此例中如果不強引用保存unlock洋机,執(zhí)行完viewDidload方法后unlock就會銷毀坠宴,如果unlock銷毀了,那么unlock相對的layer就是全透明绷旗,那么gradientLayer也會全透明喜鼓,即不強引用unlock的最終顯示效果是 屏幕上什么都看不見。

最終滑動解鎖效果圖:

效果圖

關(guān)于CAGradientLayer的屬性詳細解析可參考CAGradientLayer的一些屬性解析

三.maskView配合CAShapeLayer使用

這個Demo沒啥可講的刁标,自己看下源碼颠通,先上效果圖址晕,再上代碼膀懈。

效果圖
#import "UIImage+DDF.h"
#define   DEGREES(degrees)  ((M_PI * (degrees))/ 180.f)

@interface ViewControllerSix ()
@property (nonatomic, strong) UIView        *showView;
@property (nonatomic, strong) CAShapeLayer  *maskLayer;
@end

@implementation ViewControllerSix

- (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的隱式動畫,如果開啟隱式動畫谨垃,會出現(xiàn)卡頓現(xiàn)象启搂。
    [CATransaction setDisableActions:YES];
    _maskLayer.position = recognizer.view.center;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
    imageView.image = [UIImage imageNamed:@"Slice"];
    [self.view addSubview:imageView];
    
    
    _maskLayer = [CAShapeLayer layer];
    
    // 利用貝塞爾曲線創(chuàng)建一個圓
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0)
                                                        radius:100
                                                    startAngle:DEGREES(0)
                                                      endAngle:DEGREES(360)
                                                     clockwise:YES];
    // 獲取path
    _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;
    
    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];
}

@end

上述所有Demo源碼地址MaskViewDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刘陶,隨后出現(xiàn)的幾起案子胳赌,更是在濱河造成了極大的恐慌,老刑警劉巖匙隔,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疑苫,死亡現(xiàn)場離奇詭異,居然都是意外死亡纷责,警方通過查閱死者的電腦和手機捍掺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來再膳,“玉大人挺勿,你說我怎么就攤上這事∥蛊猓” “怎么了不瓶?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長灾杰。 經(jīng)常有香客問我蚊丐,道長,這世上最難降的妖魔是什么艳吠? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任吠撮,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泥兰。我一直安慰自己弄屡,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布鞋诗。 她就那樣靜靜地躺著膀捷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪削彬。 梳的紋絲不亂的頭發(fā)上全庸,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音融痛,去河邊找鬼壶笼。 笑死,一個胖子當著我的面吹牛雁刷,可吹牛的內(nèi)容都是我干的覆劈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼沛励,長吁一口氣:“原來是場噩夢啊……” “哼责语!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起目派,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤坤候,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后企蹭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體白筹,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年谅摄,在試婚紗的時候發(fā)現(xiàn)自己被綠了徒河。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡螟凭,死狀恐怖虚青,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情螺男,我是刑警寧澤棒厘,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站下隧,受9級特大地震影響奢人,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淆院,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一何乎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦支救、人聲如沸抢野。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽指孤。三九已至,卻和暖如春贬堵,著一層夾襖步出監(jiān)牢的瞬間恃轩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工黎做, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叉跛,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓蒸殿,卻偏偏與公主長得像筷厘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子伟桅,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Core Animation Core Animation敞掘,中文翻譯為核心動畫叽掘,它是一組非常強大的動畫處理API楣铁,...
    45b645c5912e閱讀 3,016評論 0 21
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件更扁、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評論 4 62
  • 轉(zhuǎn)載:http://www.reibang.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,157評論 0 13
  • 傍晚盖腕,伴著美麗的落霞,與老友相約浓镜,閑庭散步暢聊人生溃列,當作一種送別,也算作一份作答膛薛,更留作一次記憶听隐,區(qū)區(qū)公里之路,卻...
    落水有聲閱讀 729評論 0 1
  • 以前一直覺得一個人年輕的時候做事風風火火哄啄,斗志昂揚雅任,怎么過了年月后卻突然跟沒有出息的一樣,現(xiàn)在我也許知道答案了咨跌。人...
    高天明月55閱讀 273評論 0 0