您的位置:首页 > 移动开发 > IOS开发

IOS7的转场动画和CATransform3D简单使用

2016-01-25 20:38 441 查看
说来惭愧自己惭愧,由于自己开启了懒汉模式,一直没怎么研究过IOS7新的转场的动画,今天死磕的一天终于有点成效,还简单弄了下CATransform3D的内容

先看图



现在好多APP喜欢这样玩转场动画。。。于是就简单研究了一下 ,适合初学者,没有过多介绍深层的东西

说白了这就是执行了present的跳转代码

SecViewController *sec = [[SecViewController alloc]init];
sec.transitioningDelegate = self;  //让动画变得炫酷就靠它了
[self presentViewController:sec animated:YES completion:nil];


是不是就多了实现了一个代理?没错,靠它 我们就能实现这样的炫酷动画了。

这个代理里需要实现两个方法

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {

_presentAnimation.duration = 1;
self.presentAnimation.reverse = NO;
return self.presentAnimation;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {

self.presentAnimation.reverse = YES;

return self.presentAnimation;
}


这两个带来方法从方法名称基本就明白什么意思啦?一个是present的实现方法,一个是dismiss的实现方法。

这里面返回的是什么呢?这里就是我们返回的自定义动画

下面说说这个自定义动画的类的构造吧

接口文件

/**
*  自定义的动画类
*  实现协议------>@protocol UIViewControllerAnimatedTransitioning
*  这个接口负责切换的具体内容,也即“切换中应该发生什么”
*/
#import <Foundation/Foundation.h>

@interface CustomAnimatior : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) NSTimeInterval duration;//执行时间
@property (nonatomic, assign) BOOL reverse;//执行present或者dismiss的标识
@end


实现文件

#import <UIKit/UIKit.h>
#import "CustomAnimatior.h"
@interface CustomAnimatior()

@end
@implementation CustomAnimatior
// 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return self.duration;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {

UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *toView = toVC.view;
UIView *fromView = fromVC.view;

[self animateTransition:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
}
// 完成容器转场动画的主要方法,我们对于切换时的UIView的设置和动画都在这个方法中完成
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {

if(self.reverse){
[self executeReverseAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
} else {
[self executeForwardsAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
}

}

-(void)executeReverseAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {

UIView* containerView = [transitionContext containerView];

// positions the to- view behind the from- view
CGRect frame = [transitionContext initialFrameForViewController:fromVC];
toView.frame = frame;
CATransform3D scale = CATransform3DIdentity;
toView.layer.transform = CATransform3DScale(scale, 0.6, 0.6, 1);
toView.alpha = 0.6;

[containerView insertSubview:toView belowSubview:fromView];

CGRect frameOffScreen = frame;
frameOffScreen.origin.y = frame.size.height;

CATransform3D t1 = [self firstTransform];

[UIView animateKeyframesWithDuration:self.duration delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{

// push the from- view off the bottom of the screen
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
fromView.frame = frameOffScreen;
}];

// animate the to- view into place
[UIView addKeyframeWithRelativeStartTime:0.35f relativeDuration:0.35f animations:^{
toView.layer.transform = t1;
toView.alpha = 1.0;
}];
[UIView addKeyframeWithRelativeStartTime:0.75f relativeDuration:0.25f animations:^{
toView.layer.transform = CATransform3DIdentity;
}];
} completion:^(BOOL finished) {
if ([transitionContext transitionWasCancelled]) {
toView.layer.transform = CATransform3DIdentity;
toView.alpha = 1.0;
}
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}

-(void)executeForwardsAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {

UIView* containerView = [transitionContext containerView];

// positions the to- view off the bottom of the sceen
CGRect frame = [transitionContext initialFrameForViewController:fromVC];
CGRect offScreenFrame = frame;
offScreenFrame.origin.y = offScreenFrame.size.height;
toView.frame = offScreenFrame;

[containerView insertSubview:toView aboveSubview:fromView];

CATransform3D t1 = [self firstTransform];
CATransform3D t2 = [self secondTransformWithView:fromView];

[UIView animateKeyframesWithDuration:self.duration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeCubic animations:^{
//这里用到的是关键帧动画,也是iOS7的新特性

// push the from- view to the back
[UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.4f animations:^{
fromView.layer.transform = t1;
fromView.alpha = 0.6;
}];
[UIView addKeyframeWithRelativeStartTime:0.2f relativeDuration:0.4f animations:^{
fromView.layer.transform = t2;
}];

// slide the to- view upwards. In his original implementation Tope used a 'spring' animation, however
// this does not work with keyframes, so we siulate it by overshooting the final location in
// the first keyframe
[UIView addKeyframeWithRelativeStartTime:0.6f relativeDuration:0.2f animations:^{
toView.frame = CGRectOffset(toView.frame, 0.0, -30.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.8f relativeDuration:0.2f animations:^{
toView.frame = frame;
}];

} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];

}
-(CATransform3D)firstTransform{
CATransform3D t1 = CATransform3DIdentity;
t1.m34 = 1.0/-500; //应该透视参数 ,这个值应该是和rotation所匹配的 ,这个值越小 透视角度越大  正负代表透视方向
t1 = CATransform3DScale(t1, 0.95, 0.95, 1);//这个3D的缩放,x,y,z
t1 = CATransform3DRotate(t1, 15.0f * M_PI/180.0f, 1, 0, 0);
return t1;

}

-(CATransform3D)secondTransformWithView:(UIView*)view{

CATransform3D t2 = CATransform3DIdentity;
t2.m34 = [self firstTransform].m34;
//这是视图的偏移量 tx:X轴偏移位置,往右为正数。 ty:Y轴偏移位置,往下为正数。   tz:Z轴偏移位置,往外为正数。
t2 = CATransform3DTranslate(t2, 0, view.frame.size.height*-0.08, 0);
t2 = CATransform3DScale(t2, 0.8, 0.8, 1);

return t2;
}


在这个文件里需要引入

UIViewControllerAnimatedTransitioning的代理
并且实现两个方法

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
<pre name="code" class="objc">- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext



transitionContext
第一个方法是返回的时间 ,第二个就是方法就是我们需要自己自定义的动画。通过transitionContext可以获取到 当下的容器view

[transitionContext containerView]
以及formView和toView 这两个顾名思义 一个是当前的view 一个是切换的view。

viewControllerForKey:UITransitionContextFromViewControllerKey和
viewControllerForKey:UITransitionContextToViewControllerKey两个方法获取。

在创建动画的时候还用到了一个有关动画的特性就是关键帧动画

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
这个是穿件关键帧动画的方法
下面的是穿件单个帧动画的方法
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);


CATransform3D在实现上也没有什么难度.m文件里已经有了注释,靠自己的理解 ,可能有些3D参数理解有误,发现错误请评论谢谢
创建好这个类然后在ViewController实例化

@property (nonatomic, strong)CustomAnimatior *p

_presentAnimation = [CustomAnimatior new];

一定要实例化。。。

各位没玩过码友,赶紧试试吧

源码下载地址:
https://coding.net/u/alexgaoCode/p/IOS-translationDEMO/git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: