Core Animation动画技术

来源:互联网 发布:企业网络架构图 编辑:程序博客网 时间:2024/06/06 21:48


一.视图动画


        如下方法是视图控制器呈现模态视图方法,其中的animated:参数是设定动画效果的:

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion

        视图有一系列支持动画的属性,包括frame、bounds、center、alpha和transform等。此外,还有一些属性如下:动画延迟事件、动画曲线(淡入/淡出、线性等)、动画过度、重复次数和自动反转等属性。


       1. 动画块:

        在iOS4.0之前我们是通过UIView下面方法设置动画块的:        

[UIView beginAnimations:@"animations" context:nil];//......[UIVIew commitAnimations];
        在iOS4.0之后又推出了采用代码块(Block)的方法,这些UIView方法如下:

+animateWithDuration:animations:

+animateWithDuration:animations:completion:

+animateWithDuration:delay:options:animations:completion:

        这些方法都是UIView的类方法,需要实例化就可以直接调用其中animateWithDuration后面的参数是动画持续的时间,animations:后面是一个代码块,用来设置动画的属性。completion:也上一个代码块,是在动画结束时候调用执行的。delay:后面是动画延迟执行的时间,如果为0则动画马上执行。1


        动画代码示例:

- (IBAction)click:(id)sender{[UIView beginAnimations@"animations" context:nil];//动画开始[UIView setAnimationsDuration:1.5];//设置动画持续时间CGRect frame = self.ball.frame;frame.origin.y += 100 * flag;flag *= -1;//取反self.ball.frame = frame;[UView commitAnimations];//动画结束}
      上述代码也可以写成如下形式:

- (IBAction)click:(id)sender{[UIView animateWithDuration:1.5 animations:^{CGRect frame = self.ball.frame; frame.origin.y += 100 * flag; flag *= -1; self.ball.frame = frame;}];}


        2.动画生命周期事件:

        通过下面方法设置动画开始后的回调方法:

+ (void)setAnimationWillStartSelector:(SEL)selector

        下面方法是设置动画结束后的回调方法:

+ (void)setAnimationDidStopSelector:(SEL)selector

        而在iOS4.0之后,如果采用下面方法实现动画功能时,可以completion:实现动画结束的处理。但这些方法并没有动画开始的代码块。

+animateWithDuration:animations:completion:

+animateWithDuration:delay:options:animations:completion:

        动画代码示例:

- (IBAction)click:(id)sender{[UIView beginAnimations@"animations" context:nil];//动画开始[UIView setAnimationsDuration:1.5];//设置动画持续时间[UIView setAnimationDelegate:self];//设定动画委托对象为当前视图控制器[UIVIew setAnimationDidStopSelector:@selector(viewAnimationDone)];//是在动画结束时调用我们自定义的viewAnimationDone方法CGRect frame = self.ball.frame;frame.origin.y += 100 * flag;flag *= -1;//取反self.ball.frame = frame;[UView commitAnimations];//动画结束}
        如果想在动画开始时调用我们自定义的viewAnimationDone方法就这样写:

[UIView setAnimationWillStartSelector:@selector(viewAnimationDone)];


        3.过度动画:

        UIView的setAnimationCurve方法是设置动画曲线,动画曲线是设置动画过渡执行速度的变化情况,其中的参数是在UIViewAnimationCurve枚举中定义的常量,相关的常量还有:

typedef enum {   UIViewAnimationCurveEaseInOut,//缓入缓出,即开始和结束时减速   UIViewAnimationCurveEaseIn,//缓入,开始时减速   UIViewAnimationCurveEaseOut,//缓出,结束时减速   UIViewAnimationCurveLinear//线性,即匀速运动} UIViewAnimationCurve;

        UIView的setAnimationRepeatAutoreverses方法设置不重复动画。

        + (void)setAnimationTransition:forView:cache:方法第一个参数定义动画过渡类型,第二个参数是当前视图对象,第三个参数是是否使用缓存区。动画过渡类型相关的常量有:

typedef enum {   UIViewAnimationTransitionNone,//不设置任何过渡动画   UIViewAnimationTransitionFlipFromLeft,//设置从左往右翻转   UIViewAnimationTransitionFlipFromRight,//设置从右往左翻转   UIViewAnimationTransitionCurlUp,//设置向上翻页   UIViewAnimationTransitionCurlDown,//设置向下翻页} UIViewAnimationTransition;

        在iOS4.0之后,专门为动画过渡添加了两个方法:

+ transitionWithView:duration:options:animations:completion:,在指定的视图容器内创建动画过渡

+ transitionFromView:toView:duration:options:completion:,在指定的两个视图之间创建动画过渡

        在上面的两个方法中options参数是设置动画如何执行的常量UIViewAnimationOptions中有很多常量:

enum {   UIViewAnimationOptionLayoutSubviews            = 1 <<  0,   UIViewAnimationOptionAllowUserInteraction      = 1 <<  1,   UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2,   UIViewAnimationOptionRepeat                    = 1 <<  3,   UIViewAnimationOptionAutoreverse               = 1 <<  4,   UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5,   UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6,   UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7,   UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8,   UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9,      UIViewAnimationOptionCurveEaseInOut            = 0 << 16,   UIViewAnimationOptionCurveEaseIn               = 1 << 16,   UIViewAnimationOptionCurveEaseOut              = 2 << 16,   UIViewAnimationOptionCurveLinear               = 3 << 16,      UIViewAnimationOptionTransitionNone            = 0 << 20,   UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,   UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,   UIViewAnimationOptionTransitionCurlUp          = 3 << 20,   UIViewAnimationOptionTransitionCurlDown        = 4 << 20,   UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,   UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,   UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,};typedef NSUInteger UIViewAnimationOptions;

        其中关于动画曲线的常量有:

UIViewAnimationOptionCurveEaseInOut            = 0 << 16,   UIViewAnimationOptionCurveEaseIn               = 1 << 16,   UIViewAnimationOptionCurveEaseOut              = 2 << 16,   UIViewAnimationOptionCurveLinear               = 3 << 16,
        有关动画过渡的常量有:

UIViewAnimationOptionTransitionNone            = 0 << 20,   UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,   UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,   UIViewAnimationOptionTransitionCurlUp          = 3 << 20,   UIViewAnimationOptionTransitionCurlDown        = 4 << 20,   UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,   UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,   UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,


二.iOS 7 自定义视图过渡动画


        试图过渡即视图之间的跳转有两种情况:树形结构导航 和 模态导航,树形结构导航是通过UINavigationController控制视图堆栈实现视图过渡,模态导航是通过UIViewController控制视图实现的。

        树形结构导航自定义过渡动画涉及实现两个协议:UIViewControllerAnimatedTransitioning和UINavigationControllerDelegate。我们需要自己定义动画对象,这个对象要求实现UIViewControllerAnimatedTransitioning协议,UIViewControllerAnimatedTransitioning主要定义了两个方法:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext//执行自定义动画

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext//设置动画执行时间

        模态导航自定义过渡动画需要在视图控制器中实现UIViewControllerTransitioningDelegate协议,该协议定义的方法:

- animationControllerForPresentedController:presentingController:sourceController:,在呈现视图时候调用
- animationControllerForDismissedController:,在关闭视图时候调用



三. UIKit力学


        UIDynamicAnimator是用来存放要使用的力学行为(UIDynamicBehavior),这里力学行为有6个子类:UIAttachmentBehavior、UICollisionBehavior、UIGravityBehavior、UIPushBehavior、UISnapBehavior和UIDynamicItemBehavior。对于每一个力学行为都有多个力学项目(UIDynamicItem)。而UIDynamicAnimator的ReferenceView属性指向了所要呈现的视图。


        提示:一个UIDynamicAnimator可以包含多个力学行为,通过addBehavior:方法添加力学行为。一个力学行为可以包含多个力学项目,通过addItem:方法添加。还有UIDynamicAnimator与ReferenceView之间是1:1的关系,即一个UIDynamicAnimator只有一个ReferenceView与之对应。



        UIKit力学行为包含了:重力(UIGravityBehavior)、碰撞(UICollisionBehavior)、吸附(UIAttachmentBehavior)、推(UIPushBehavior)、甩(UISnapBehavior)和行为限制(UIDynamicItemBehavior)。除了行为限制(UIDynamicItemBehavior)外,其中的5种力学行为使用起来都大同小异。

        

        1.重力行为UIGravityBehavior

        重力行为默认向下,相关示例代码如下:

UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];//创建UIDynamicAnimator对象,其中self.view是ReferenceViewUIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];//创建UIGravityBehavior对象[animator addBehavior:gravity];//将行为力学gravity添加到UIDynamicAnimator对象中[gravity addItem:myView];//将myView添加到力学行为gravity中去,其中myView是要模拟重力行为运动的视图对象
        上面的代码也可以采用如下写法:

UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[myView]];//参数是一个数组[animator addBehavior:gravity];
        

        2.碰撞行为UICollisionBehavior

        我们可以检测运动物体(视图对象)与ReferenceView,也可以检测与其他物体(视图对象)是否有碰撞发生。

        检测是否与ReferenceView边界发生碰撞的方法如下:

[collision setTranslatesReferenceBoundsIntoBoundary:YES];

        检测是否与其他的物体(视图对象)边界发生碰撞的方法如下:

CGPoint p1 = barrier.frame.origin;

CGPoint p2 = CGPointMake(p1.x + barrier.frame.size.width, p1.y);

[collision addBoundaryWithIdentifier:@"barrier" fromPoint:p1 toPoint:p2];

        barrier对象是其他的视图对象,我们主要是addBoundaryWithIdentifier:fromPoint:toPoint:方法实现检测的,其中需要定义一个标识@"barrier",还有其实点fromPoint和结束点toPoint,这是定义了一条直线,有物体从上面落下,我们只需要关心碰撞物体的x轴投影就可以了,与碰撞物体厚度无关。


        3.吸附行为UIAttachmentBehavior

       UIAttachmentBehavior的length属性就是标识两个物体之间的距离,单位是“点”。

UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:AView attachedToItem:BView];//AView和BView是彼此吸附的视图对象


        4.推行为UIPushBehavior

        推行为可以视图对象朝某个方向运动,这个推力有瞬间(UIPushBehaviorModeInstantaneous)和持续(UIPushBehaviorModeContinuous)两种方式。

UIPushBehavior *push = [[itemBehaviour alloc] initWithItems:@[myView] mode:UIPushBehaviorModeInstantaneous];

        设置推行行为需要考虑方向和大小,这是因为力是矢量。设置代码如下:

CGVector pushDirection = {0.5, -0.5};//矢量pushDirection 是结构体CGVector类型,其中第一个参数0.5代表x轴正方向,第二个参数-0.5代表y轴负方向,注意y轴正方向是向下的,因此y轴负方向是向上。所有{0.5, -0.5}表示推力的方向是指向右上角方向(与x轴夹角是45°)。

[push setPushDirection:pushDirection];

[push setMagnitude:5.0f];//设置力度,默认是1.0f。

        如果你觉得上面的代码有点繁琐,可以使用setAngel:magnitude:方向替换。

[push setAngel:-M_PI/4 magnitude:5.0f];//setAngel是设置力的方向角度,-M_PI/4表示与x轴夹角,负数代表向上。magnitude是设置力度的大小。


        5.甩行为UISnapBehavior

        甩行为能够是物体朝着某个目标点甩出(或抛出),并且有瞬间加速度,由慢及快,再由快及慢,最后停止在目标点。

CGPoint p = [[self view] center];

UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:myView snapToPoint:p];//p为目标点


        6.行为限制UIDynamicItemBehavior

        它是用了设置力学行为的参数的,这些参数包括了一些物理属性。这些属性如下:

        density密度

        elasticity弹力系数

        friction摩擦力系数

        resistance阻力,物体运动的时候,在线性方向的阻力。

        allowsRotation是否允许旋转。

        angularResistance角阻力,物体旋转的时候,旋转方向的阻力。

        示例代码如下:

UIDynamicItemBehavior *itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:@[myView]];

[itemBehaviour setElasticity:1.0];

[itemBehaviour setAllowsRotation:YES];

[itemBehaviour setFriction:0.0];

[itemBehaviour setResistance:0.0];

[animator addBehavior:itemBehaviour];

        


四.运动效果

   

        运动效果的API主要是UIInterpolatingMotionEffect类,iOS 7 还在UIView中添加了- (void)addMotionEffect:(UIMotionEffect *)effect方法,这个方法可以添加UIMotionEffect 对象到视图,UIMotionEffect是UIInterpolatingMotionEffect的父类。


//设置山在x轴的偏移范围-50.0~50.0

UIInterpolatingMotionEffect *mountainEffectX;

mountainEffectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];

mountainEffectX.maximumRelativeValue = @50.0;

mountainEffectX.minimumRelativeValue = @-50.0;

[self.mountain addMotionEffect:mountainEffectX];


//设置山在x轴的偏移范围-100.0~100.0

UIInterpolatingMotionEffect *treeEffectX;

treeEffectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];

treeEffectX.maximumRelativeValue = @100.0;

treeEffectX.minimumRelativeValue = @-100.0;

[self.mountain addMotionEffect:treeEffectX];


        其中keyPath为"center.x",表示运动效果对应的属性,type参数type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis表示沿水平方向运行效果。maximumRelativeValue 表示设置运动最大值,其中@50.0表示NSNumber对象,最后一行表示将mountainEffectX对象添加到ImageView对象(self.mountain)中。



五.Core Animation框架


         1.图层

         我们可以自定义图层,重写绘制方法,从而实现自己绘制图层的目的,图层也有层次关系,有自己的子图层。视图是重量级对象,他负责绘制和事件响应,图层负责绘制。事实上视图依赖于图层实现绘制处理。


- (void)viewDidLoad

{

[super viewDidLoad];


UIImage *image = [UIImage imageNamed:@"ball.png"];

self.ballLayer = [CALayer layer];//创建一个图层对象,注意[CALayer layer]方法不是单例模式的,也就是说每次调用都有不同的图层对象产生,在视图中可以有很多图层,他们是通过zPosition属性来区别他们在立体空间中的深度,即z轴上的顺序。

self.ballLayer.contents = (id)[image CGImage];//可以返回CGImageRef类的数据,图层的contents属性是图层的内容,他能接收CGImageRef类型数据,或者是其他图层的内容

self.ballLayer.bounds = CGRectMake(0.0.f,0.0f,125.0f,125.0f);//设定图层的边界

self.ballLayer.contentsGravity = kCAGravityResizeAspect;//设置图层内容的摆放方式,其中kCAGravityResizeAspect常量可以使内容重新调整保持原样

self.ballLayer.position = CGPointMake(CGRectGetMidX(self.view.bounds),CGRectGetMidY(self.view.bounds));//设置图层的position(位置)属性,其中CGRectGetMidX(self.view.bounds)函数计算出视图的中心点的x坐标,CGRectGetMidY(self.view.bounds)函数计算出视图的中心点的y坐标。


[self.view.layer addSublayer:self.ballLayer];//将图层添加到当前图层上来

}


        2.隐式动画

        在Core Animation框架中有两种形式的动画,隐式动画、显示动画。

        隐式动画:这是一种最简单的动画,不用设置定时器,不用考虑线程或者重画,它的很多属性都是默认的。前面介绍的视图动画属于隐式动画。

        显示动画:是一种使用CABasicAnimation创建的动画,通过CABasicAnimation,可以更明确的定义属性如何改变动画。显示动画还有更复杂的显示动画类型——关键帧动画,这里可以定义动画的起点和终点,还可以定义某些帧之间的动画。使用CAKeyframeAnimation创建动画。


- (void)viewDidLoad

{

[super viewDidLoad];

_plane.layer.opacity = 0.25;//设置图片视图的图层不透明度为0.25,在UIView里对应的是alpha属性,是等同的

}

- (IBAction)movePlane:(id)sender

{

CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(180,200);//创建平移放射变换变量

[_plane.layer setAffineTransform:moveTransform];//设置图片层的放射变换,即从当前位置平移到(180,200),所以图片就动起来了

_plane.layer.opacity = 1;//设置图片的不透明度为1

}


        3.显示动画

        在使用显示动画不比定义图层属性变化,也不必执行他们,而是通过CABasicAnimation逐个定义动画。其中每个动画都含有各自的持续时间、重复次数等属性。然后使用addAnimation:forKey:方法分别将每个动画应用到图层的特定属性中。

        创建显示动画可以通过如下代码实现:

[CABasicAnimation animationWithKeyPath:@"opacity"];

        animationWithKeyPath后面的参数是图层的属性,opacity是不透明属性,因此上面代码创建的动画是针对图层不透明度变化的动画。


       4.关键帧动画


       5.使用路径

0 0
原创粉丝点击