1. 實(shí)現(xiàn)效果:
項(xiàng)目中需要添加一個效果,彈出彈框時网棍,底部控制器向內(nèi)凹陷黔龟,類似淘寶加入購物車動畫效果,如下圖:
2. 實(shí)現(xiàn)方法
這里有2種實(shí)現(xiàn)方法滥玷,一種是通過自己代碼氏身,另一種通過第三方框架
2.1 自己代碼實(shí)現(xiàn)
2.1.1 此處只寫明關(guān)鍵步驟的實(shí)現(xiàn)原理,view根據(jù)自己的頁面自定義惑畴,步驟:
- 按鈕點(diǎn)擊事件[pop]中蛋欣,在AnimationVC上面添加一個MaskView(可根據(jù)需求在MaskView上添加點(diǎn)擊退出的按鈕)
- 在Window上,添加彈出的popView
- 添加動畫效果如贷,凹陷view
- 在確定/取消的方法中調(diào)用[self close];
2.1.2 這里先解釋下m34:
transform本身就是個結(jié)構(gòu)體陷虎,首先要實(shí)現(xiàn)View的透視效果(近大遠(yuǎn)小)杠袱,就是通過它來實(shí)現(xiàn)的.
CATransform3D transform3D = CATransform3DIdentity;
transform3D.m34 = 1.0 / -500;```
m34負(fù)責(zé)z軸方向的translation(移動)尚猿,m34= -1/D,默認(rèn)值是0,也就是說D無窮大楣富,這意味layer in projection plane(投射面)和layer in world coordinate重合了凿掂。
D越小透視效果越明顯。所謂的D菩彬,是eye(觀察者)到投射面的距離缠劝。
2.1.3 代碼:
1. 動畫開始
- (void)pop {
// 隱藏tabbar
self.tabBarController.tabBar.hidden = YES;
// 1.view上添加遮罩
[self.view addSubview:self.maskView];
// 2.window上添加彈框
[[UIApplication sharedApplication].windows[0] addSubview:self.popView];
CGRect rec = self.popView.frame;
rec.origin.y = SCREEN_HEIGHT - FYpopView_HEIGHT;
[UIView animateWithDuration:0.3 animations:^{
// 第一段操作
// 逆時針X軸旋轉(zhuǎn) 縮小到0.95倍潮梯,實(shí)現(xiàn)向內(nèi)傾斜凹陷的透視效果
self.view.layer.transform = [self transform1];
} completion:^(BOOL finished) {
// 第二段操作,
// 把transform設(shè)置為初始化惨恭,透視效果和第一段一樣秉馏,
// 讓他回歸到正常(不傾斜),
// 同時大小最終為0.8脱羡,高度向上移動一點(diǎn)點(diǎn)萝究,
// 添加maskView,添加popView
[UIView animateWithDuration:0.3 animations:^{
self.view.layer.transform = [self transform2];
self.maskView.alpha = 0.5;
self.popView.frame = rec;
} completion:^(BOOL finished) {
}];
}];
}
2. 動畫結(jié)束
- (void)close {
CGRect rec = self.dimensionView.frame;
rec.origin.y = self.view.bounds.size.height;
// 動畫回去
[UIView animateWithDuration:0.3 animations:^{
self.dimensionView.frame = rec;
self.maskView.alpha = 0;
self.view.layer.transform = [self transform1];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
// 折疊完之后讓transform回歸到正常水平
self.view.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {
[self.dimensionView removeFromSuperview];
}];
}];
self.tabBarController.tabBar.hidden = NO;
}
3. 關(guān)鍵形變方法
// 第一次形變
- (CATransform3D)transform1{
// 每次進(jìn)來都進(jìn)行初始化 回歸到正常狀態(tài)
CATransform3D form1 = CATransform3DIdentity;
// m34就是實(shí)現(xiàn)視圖的透視效果的(俗稱近大遠(yuǎn)酗惫蕖)
form1.m34 = 1.0/-900;
// 縮小
form1 = CATransform3DScale(form1, 0.85, 0.85, 1);
// x軸旋轉(zhuǎn)
form1 = CATransform3DRotate(form1, 15.0 * M_PI/180.0, 1, 0, 0);
return form1;
}
// 第二次形變
- (CATransform3D)transform2{
// 初始化 再次回歸正常
CATransform3D form2 = CATransform3DIdentity;
// 用和上面相同的m34 來設(shè)置透視效果
form2.m34 = [self transform1].m34;
// 向上平移一丟丟 讓視圖平滑點(diǎn)
form2 = CATransform3DTranslate(form2, 0, self.view.frame.size.height * (-0.08), 0);
// 最終縮小到0.8倍
form2 = CATransform3DScale(form2, 0.8, 0.8, 1);
return form2;
}
2.2 通過第三方框架實(shí)現(xiàn) KNSemiModalViewController
這是國外一個比較成熟的庫帆竹,自定義非常高,可彈出view脓规,也可彈出控制器栽连,但是用時會遇到些問題
2.2.1 使用步驟:
- 將Source文件夾拖到項(xiàng)目中
- 添加QuartzCore.framework
- 導(dǎo)入頭文件#import "UIViewController+KNSemiModal.h"
- 調(diào)用 [self presentSemiModalView:myView] 彈出動畫
- 調(diào)用[self dismissSemiModalView] 關(guān)閉動畫
2.2.2 可能遇到的問題:
1. 問題1
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解決方法:add typedef
typedef NS_ENUM(NSUInteger, KNSemiModalTransitionStyle) {
KNSemiModalTransitionStyleSlideUp,
KNSemiModalTransitionStyleFadeInOut,
KNSemiModalTransitionStyleFadeIn,
KNSemiModalTransitionStyleFadeOut,
};
2. 問題2
Exception: Defaults must have been set when accessing
解決方法:
如果你要的根控制器是有導(dǎo)航欄的
[self.navigationController presentSemiViewController....]
如果沒有導(dǎo)航欄
[self presentSemiViewController....]