仿網(wǎng)易云音樂(lè)廣告頁(yè)的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

先上效果圖:

效果圖
效果圖

細(xì)心的小伙伴會(huì)發(fā)現(xiàn)躏鱼,現(xiàn)在 網(wǎng)易云音樂(lè)的廣告頁(yè) 以及 微信相冊(cè)中點(diǎn)擊查看評(píng)論 都用了該轉(zhuǎn)場(chǎng)動(dòng)畫(huà)。作為一名 iOS 程序員,本能的想去實(shí)現(xiàn)它稍途。

說(shuō)明:本篇博文參考了 onevcat 的 WWDC 2013 Session筆記 以及 GitHub 上的開(kāi)源項(xiàng)目劫瞳。不打算先理論了倘潜,直接拿 demo 項(xiàng)目開(kāi)擼。

項(xiàng)目結(jié)構(gòu)

很顯然志于,有兩個(gè) ViewController涮因,在本例中分別是 MainViewController(下文簡(jiǎn)稱(chēng) mainVC) 和 ForwardViewController(簡(jiǎn)稱(chēng) forwardVC)。

首先伺绽,我們讓 mainVC 聲明 UIViewControllerTransitioningDelegate 協(xié)議养泡,并實(shí)現(xiàn) - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;方法。

該方法需要你返回一個(gè)自定義的動(dòng)畫(huà)奈应,該動(dòng)畫(huà)類(lèi)型為 NSObject 澜掩,并需要實(shí)現(xiàn) UIViewControllerAnimatedTransitioning 協(xié)議。

因此杖挣,接下來(lái)我們需要實(shí)現(xiàn)這樣一個(gè)實(shí)現(xiàn) UIViewControllerAnimatedTransitioning 協(xié)議的 object输硝,不妨取名為 NeteaseTransitionAnimation。

實(shí)現(xiàn) NeteaseTransitionAnimation

在本例中程梦,我們著重看 UIViewControllerAnimatedTransitioning 協(xié)議中的兩個(gè)方法点把,一是 - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;,第二個(gè)是 - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext屿附。

第一個(gè)方法傳入動(dòng)畫(huà)的時(shí)間長(zhǎng)度郎逃,在這里我們?cè)O(shè)置為 0.8 秒,我們主要在第二個(gè)方法中設(shè)定具體的動(dòng)畫(huà)效果挺份。

第二個(gè)方法中有一個(gè)很重要的 UIViewControllerContextTransitioning 類(lèi)型的上下文對(duì)象 transitionContext褒翰,通過(guò)該對(duì)象我們可以獲得切出以及切入的 VC 從而設(shè)置動(dòng)畫(huà)的具體參數(shù)等。不多說(shuō),接下來(lái)直接上具體實(shí)現(xiàn)步驟及相應(yīng)代碼优训。

獲得切出和切入的 ViewController

UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

獲得 containerView 并將待切入的 view 加入其中

UIView *containerView = [transitionContext containerView];
[containerView addSubview:toVC.view];

有人問(wèn)朵你,containerView 是用來(lái)干嘛的。官方定義: * The view that acts as the superview for the views involved in the transition. * 揣非。并且抡医,它會(huì)自動(dòng)的將當(dāng)前所在的 viewController 的 view 加入其中。

使用 CATransform3D 實(shí)現(xiàn)動(dòng)畫(huà)過(guò)程

這步應(yīng)該算是本篇中最核心的一步早敬。關(guān)于涉及到的動(dòng)畫(huà)知識(shí)忌傻,建議先看iOS 核心動(dòng)畫(huà)高級(jí)技巧中的 3D 變換這一章,在本篇博文中就不具體談了搞监。
代碼:

CATransform3D transform = CATransform3DIdentity;
transform.m34 = -0.002; // 設(shè)置透視效果水孩,一般設(shè)為 -0.002
[containerView.layer setSublayerTransform:transform]; // 將動(dòng)畫(huà)影響到父視圖下的所有子視圖

CGRect initialFrame = [transitionContext initialFrameForViewController:fromVC];
toVC.view.frame = initialFrame; // 給 toVC 設(shè)置初始 frame

讓我們重新看一下開(kāi)頭的效果圖,可以將整個(gè)動(dòng)畫(huà)過(guò)程分成 3 個(gè)階段琐驴。(假設(shè)我們將一個(gè)周期的總時(shí)間設(shè)為 t俘种,并規(guī)定逆時(shí)針轉(zhuǎn)動(dòng)為正,順時(shí)針轉(zhuǎn)動(dòng)為負(fù)绝淡,逆順指針均從視角的正上往正下看)

0 階段

fromVC 初始在原位宙刘,而 toVC 初始化在 pi / 2 的位置。見(jiàn)圖:

具體代碼:
toVC.view.layer.transform = CATransform3DMakeRotation(M_PI_2, 0.0, 1.0, 0.0);

0 ~ t / 2 階段

fromVC 順時(shí)針從 0 度轉(zhuǎn)到 - pi / 2 的位置够委,toVC 在 pi / 2 位置保持不動(dòng)荐类。(這時(shí)在視覺(jué)上二者重合)

t / 2 ~ t 階段

toVC 從初始的 pi / 2 位置順時(shí)針轉(zhuǎn)到 0 位置。

0 ~ pi 階段的具體代碼:

[UIView animateKeyframesWithDuration:duration delay:0.0 options:0 animations:^{
        [UIView addKeyframeWithRelativeStartTime:0.0
                                relativeDuration:0.5
                                      animations:^{
                                          fromVC.view.layer.transform = CATransform3DMakeRotation(- M_PI_2, 0.0, 1.0, 0.0);
                                    }];
        [UIView addKeyframeWithRelativeStartTime:0.5
                                relativeDuration:0.5
                                      animations:^{
                                          toVC.view.layer.transform =  CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
                                    }];
                              } completion:^(BOOL finished) {
                                  [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];

值得提一下 [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; 茁帽,如果沒(méi)有取消動(dòng)畫(huà)的話(huà)玉罐,即為 [transitionContext completeTransition: YES]。在該方法中潘拨,* UIKit will ensure the final state is consistent and remove the fromView from the container. * 吊输,即,在我們這里铁追,該方法將會(huì)移除 fromVC.view 季蚂。

結(jié)尾

該動(dòng)畫(huà)源碼已上傳 GitHub,鏈接戳此琅束。有問(wèn)題可以提 issue 或者直接在本博文下方的評(píng)論框中進(jìn)行評(píng)論扭屁。

其實(shí)該動(dòng)畫(huà)并不難,建議對(duì)著源碼多比較涩禀,并按 option + 函數(shù)名 查看官方定義料滥,會(huì)很有收獲的。

參考鏈接也不另給了艾船,基本都是 Apple 官方的文檔葵腹,沒(méi)有什么資料比官方文檔更有說(shuō)服力了高每。

聯(lián)系我

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市践宴,隨后出現(xiàn)的幾起案子鲸匿,更是在濱河造成了極大的恐慌,老刑警劉巖阻肩,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件带欢,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡磺浙,警方通過(guò)查閱死者的電腦和手機(jī)洪囤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)徒坡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)撕氧,“玉大人,你說(shuō)我怎么就攤上這事喇完÷啄啵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵锦溪,是天一觀(guān)的道長(zhǎng)不脯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)刻诊,這世上最難降的妖魔是什么防楷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮则涯,結(jié)果婚禮上复局,老公的妹妹穿的比我還像新娘。我一直安慰自己粟判,他們只是感情好亿昏,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著档礁,像睡著了一般角钩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呻澜,一...
    開(kāi)封第一講書(shū)人閱讀 52,807評(píng)論 1 314
  • 那天递礼,我揣著相機(jī)與錄音,去河邊找鬼羹幸。 笑死脊髓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的睹欲。 我是一名探鬼主播供炼,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼一屋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了袋哼?” 一聲冷哼從身側(cè)響起冀墨,我...
    開(kāi)封第一講書(shū)人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涛贯,沒(méi)想到半個(gè)月后诽嘉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弟翘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年虫腋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稀余。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悦冀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出睛琳,到底是詐尸還是另有隱情盒蟆,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布师骗,位于F島的核電站历等,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏辟癌。R本人自食惡果不足惜寒屯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍少。 院中可真熱鬧寡夹,春花似錦、人聲如沸仍侥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)农渊。三九已至患蹂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砸紊,已是汗流浹背传于。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留醉顽,地道東北人沼溜。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像游添,于是被迫代替她去往敵國(guó)和親系草。 傳聞我的和親對(duì)象是個(gè)殘疾皇子通熄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

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