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

来源:互联网 发布:丝绒窗帘知乎 编辑:程序博客网 时间:2024/05/22 13:32

说来惭愧自己惭愧,由于自己开启了懒汉模式,一直没怎么研究过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




0 0
原创粉丝点击