CoreAnimation之轉(zhuǎn)場之圓圈縮放動畫

先看動畫效果:


圓圈轉(zhuǎn)場動畫.gif

間客的APP上之前是有這個動畫的,拜讀了大神的文章:iOS自定義轉(zhuǎn)場詳解03——實現(xiàn)通過圓圈放大縮小的轉(zhuǎn)場動畫,博客里面很詳細蛤织。

因為要自定義轉(zhuǎn)場,所以我們需要一個新的對象集成NSObject,并且遵守轉(zhuǎn)場動畫的協(xié)議,UIViewControllerAnimatedTransitioning

介紹個知識點:

1儿礼、CGRectInsetCGRect
CGRectInset (
CGRect rect,
CGFloat dx,
CGFloat dy);
該結(jié)構(gòu)體的應(yīng)用是以原rect為中心,再參考dx庆寺,dy蚊夫,進行縮放或者放大。

2懦尝、CGRectOffsetCGRect
CGRectOffset(
CGRect rect,
CGFloat dx,
CGFloat dy); 
相對于源矩形原點rect(左上角的點)沿x軸和y軸偏移, 再rect基礎(chǔ)上沿x軸和y軸偏移

// This is used for percent driven interactive transitions, as well as for
// container controllers that have companion animations that might need to
// synchronize with the main animation.
設(shè)置轉(zhuǎn)場動畫的時間知纷。
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;

// This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
轉(zhuǎn)場的上下文
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

關(guān)于這個參數(shù)transitionContext壤圃, 該參數(shù)是一個實現(xiàn)了 UIViewControllerContextTransitioning可以讓我們訪問一些實現(xiàn)過渡所必須的對象。
UIViewControllerContextTransitioning 協(xié)議中有一些方法:

  • (UIView *)containerView;
    //轉(zhuǎn)場動畫發(fā)生的容器
  • (UIViewController *)viewControllerForKey:(NSString *)key;
    // 我們可以通過它拿到過渡的兩個 ViewController琅轧。

大致思路是這樣從伍绳,我們畫兩個內(nèi)塞爾曲線的圓,第一個小圓的frame和右上角圓形按鈕的大小一樣乍桂,第二個大圓則是覆蓋了整個屏幕冲杀。然后,去設(shè)置view.layer.mask屬性睹酌,讓這個mask從小圓動畫到大圓权谁。

以push 動畫為例:pop動畫不過是起終點的mask路徑相反罷了。

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{

   
    ViewController * fromVC = (ViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    DetailViewController *toVC = (DetailViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *contView = [transitionContext containerView];

    UIButton *button = fromVC.button;
    
    
    UIBezierPath *maskStartBP =  [UIBezierPath bezierPathWithOvalInRect:button.frame];    
    [contView addSubview:fromVC.view];
    [contView addSubview:toVC.view];

    
    
    //創(chuàng)建兩個圓形的 UIBezierPath 實例憋沿;一個是 button 的 size 旺芽,另外一個則擁有足夠覆蓋屏幕的半徑。最終的動畫則是在這兩個貝塞爾路徑之間進行的
    
    CGPoint finalPoint;
    //判斷觸發(fā)點在那個象限
    if(button.frame.origin.x > (toVC.view.bounds.size.width / 2)){
        if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
            //第一象限
            finalPoint = CGPointMake(button.center.x - 0, button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
        }else{
            //第四象限
            finalPoint = CGPointMake(button.center.x - 0, button.center.y - 0);
        }
    }else{
        if (button.frame.origin.y < (toVC.view.bounds.size.height / 2)) {
            //第二象限
            finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - CGRectGetMaxY(toVC.view.bounds)+30);
        }else{
            //第三象限
            finalPoint = CGPointMake(button.center.x - CGRectGetMaxX(toVC.view.bounds), button.center.y - 0);
        }
    }
    
    
    
    CGFloat radius = sqrt((finalPoint.x * finalPoint.x) + (finalPoint.y * finalPoint.y));
    UIBezierPath *maskFinalBP = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(button.frame, -radius, -radius)];
    
    
    //創(chuàng)建一個 CAShapeLayer 來負責展示圓形遮蓋
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = maskFinalBP.CGPath; //將它的 path 指定為最終的 path 來避免在動畫完成后會回彈
    toVC.view.layer.mask = maskLayer;
    maskLayer.backgroundColor =[UIColor redColor].CGColor;
    
    CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    maskLayerAnimation.fromValue = (__bridge id)(maskStartBP.CGPath);
    maskLayerAnimation.toValue = (__bridge id)((maskFinalBP.CGPath));
    maskLayerAnimation.duration = [self transitionDuration:transitionContext];
    maskLayerAnimation.timingFunction = [CAMediaTimingFunction  functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    maskLayerAnimation.delegate = self;
    
    [maskLayer addAnimation:maskLayerAnimation forKey:@"path"];
    
    ```
    
    
 結(jié)束動畫后設(shè)置:

pragma mark - CABasicAnimation的Delegate

  • (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{

    //告訴 iOS 這個 transition 完成
    [self.transitionContext completeTransition:![self. transitionContext transitionWasCancelled]];
    //清除 fromVC 的 mask
    [self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
    [self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;

}



>自定義完push 動畫后我們需要進行設(shè)置卤妒,因為所有的子控制器由UINavgationController進行管理甥绿,所有我們需要在ViewCotroller中實現(xiàn)代理;

@interface ViewController ()<UINavigationControllerDelegate>

最好在`viewWillAppear`中設(shè)置代理

-(void)viewWillAppear:(BOOL)animated{
self.navigationController.delegate = self;
}

實現(xiàn)代理:

pragma mark - UINavigationControllerDelegate

  • (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
    animationControllerForOperation:(UINavigationControllerOperation)operation
    fromViewController:(UIViewController *)fromVC
    toViewController:(UIViewController *)toVC{
    if (operation == UINavigationControllerOperationPush) {

      PingTransition *ping = [PingTransition new];
      return ping;
    

    }else{
    return nil;
    }
    }

本文demo地址:[圓圈轉(zhuǎn)場動畫](https://github.com/liuxinixn/CircleZoomView/tree/master)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市则披,隨后出現(xiàn)的幾起案子共缕,更是在濱河造成了極大的恐慌,老刑警劉巖士复,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件图谷,死亡現(xiàn)場離奇詭異,居然都是意外死亡阱洪,警方通過查閱死者的電腦和手機便贵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冗荸,“玉大人承璃,你說我怎么就攤上這事“霰荆” “怎么了盔粹?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長程癌。 經(jīng)常有香客問我舷嗡,道長,這世上最難降的妖魔是什么嵌莉? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任进萄,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘中鼠。我一直安慰自己可婶,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布兜蠕。 她就那樣靜靜地躺著扰肌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪熊杨。 梳的紋絲不亂的頭發(fā)上曙旭,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音晶府,去河邊找鬼桂躏。 笑死,一個胖子當著我的面吹牛川陆,可吹牛的內(nèi)容都是我干的剂习。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼较沪,長吁一口氣:“原來是場噩夢啊……” “哼鳞绕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吩坝,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冤竹,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年茬射,在試婚紗的時候發(fā)現(xiàn)自己被綠了鹦蠕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡在抛,死狀恐怖钟病,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刚梭,我是刑警寧澤档悠,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站望浩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惰说。R本人自食惡果不足惜磨德,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧典挑,春花似錦酥宴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至琳水,卻和暖如春肆糕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背在孝。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工诚啃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人私沮。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓始赎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仔燕。 傳聞我的和親對象是個殘疾皇子造垛,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜晰搀,今天將帶大家一窺iOS動畫全貌五辽。在這里你可以看...
    F麥子閱讀 5,110評論 5 13
  • 前言的前言 唐巧前輩在微信公眾號「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各項指標...
    VincentHK閱讀 5,360評論 3 44
  • 在iOS中隨處都可以看到絢麗的動畫效果厕隧,實現(xiàn)這些動畫的過程并不復(fù)雜奔脐,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,485評論 6 30
  • iOS動畫篇之CoreAnimation動畫 9月 22, 2016發(fā)布在Objective-C App如果想被大...
    白水灬煮一切閱讀 2,026評論 0 0
  • Core Animation Core Animation吁讨,中文翻譯為核心動畫髓迎,它是一組非常強大的動畫處理API,...
    45b645c5912e閱讀 3,027評論 0 21