Animation 动画
A.属性动画;
B.一次进行多个动画;
C.基于物理的动画。

Core Animation
是现有、强大的动画框架。

A.UIView的属性动画
属性变化是立即完成的,但是在屏幕上的显示会经过一段时间的动画变化,
等动画结束后才显示正确的属性,可以参考UIView的方法animationWithDuration:...
B.UIView的任意显示变化动画
如跳转flipping、溶解dissolving、弯曲curling整个视图等。
使用UIView的类方法:transitionWithView:...
C.动态动画
给可以做动画的物体(通常是UIView)指定物理特性,
如重力、推力、物体间的联系、碰撞边界等,让物理效果发生。






1UIView Animation


A. 一系列UIView的属性的变化可以实现一段动画:


帧(frame)动画;


变换(transform)动画,如translation位置移动、ratation旋转和scale缩放;


alpha动画,改变的是透明度。



B.使用UIView的方法和block来实现动画


类方法需要动画参数和一个动画block参数,动画block包含改变UIView的代码,


大部分时候还有一个"completion block",当动画完成后执行这个block;


block中改变UIView的变化是马上完成的(虽然它们看起来是经过了一段时间)。



C.UIView中关于动画的类方法


+(void)animateWithDuration:(NSTimeInterval)duration
                     delay:(NSTimeInterval)delay
                   options:(UIViewAnimationOptions)options
                animations:(void (^)(void))animations
                completion:(void (^)(BOOL finished))completion;

例:


[UIView animateWithDuration:3.0
                      delay:0.0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{myView.alpha = 0.0;}
                 completion:^(BOOL fin) {if (fin) [myView removeFromSuperView]; }];

以上代码将使myView在3秒内逐渐淡出(代码执行后马上开始,没有延迟)。


然后在动画结束后会将myView从类层次结构中删除。


如果在3秒内其它人把alpha修改成非0,那么删除动作将不会执行。



另一个例子:


if (myView.alpha == 1.0) {
    [UIView animateWithDuration:3.0
                          delay:0.0
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{myView.alpha = 0.0;}
                     completion:^nil];
    NSLog(@"alpha is %f. ", myView.alpha);
}

以上代码也将使myView在3秒内逐渐淡出,但是要经过2秒的延迟后再开始。


NSLog将会麻烦执行,不会等3秒或5秒的延迟,而且它会打印:"alpha is 0."


换句话说,动画block改变属性的操作是马上执行的,但是动画本身是在2秒后


才开始,并且经历了3秒钟。




D.UIViewAnimationOptions 

 BeginFromCurrentState        // 打断其它正在进行的相关的属性动画 

 AllowUserInteraction        // 动画进行是允许处理手势 

 LayoutSubviews                    // 

 Repeat                                    // 一直重复动画 

 AutoReverse                            // 动画运行完后以相反的方式再执行一遍 

 OverrideInheritedDuration     // 

 OverrideInheritedCurve            // 

 AllowAnimatedContent                // 

 CurveEaseInEaseOut                    // 

 CurveEaseIn                                    // 

 CurveLinear                                    //

E.有时你想一次进行多个动画,如:


By flipping view over UIViewAnimationOptionsTransitionFlipFrom{left,Right,Top,Bottom}


Dissolving from old to new state UIViewAnimationOptionsTransitionCrossDissolve


Curling up or down UIViewAnimationOptionsTransitionCurling{Up,Down}


只需要把以上变化代码放到以下UIview类的类方法的动画block参数中:


+(void)transitionWithView:(UIView *)view
                 duration:(NSTimeInterval)duration
                  options:(UIViewAnimationOptions)options
               animations:(void (^)(void))animations
               completion:(void (^) (BOOL finished))completion;





F.改变视图层次结构的动画有点不一样


以动画方式用一个view替换另一个view:


+(void)transitionFromView:(UIView *)fromView
                   toView:(UIView *)toView
                 duration:(NSTimeInterval)duration
                  options:(UIViewAnimationOptions)options
               completion:(void (^)(BOOL finished))completion;

如果你想使用hidden属性,请包括UIViewAnimationOptionShowHideTransitionViews;


否则以上调用将在视图层次结构中删除fromView、增加toView;




2.Dynamic 动画


跟上述的动画实现方式有些不一样,


设置一些物理关联的动画对象,让它们运行,直到它们的速度最终变成0.


也可以比较容易的通过设置,让它们的速度永远不会变成0,但是这可能引发性能问题。


步骤:


创建一个UIDynamicAnimator对象


给这个对象添加UIDynamicBehaviors(gravity,collisions,etc).


向UIDynamicBehaviors中添加UIDynamicItems.


就这么简单! 然后相关的动作将会开始运行。



创建一个UIDynamicAnimator对象


UIDynamicAnimator * animator = [[UIDynamicAnimator allco] init];


如果动画是针对view的,那么view一定要在视图层次结构中。



创建并添加UIDynamicBehaviors


e.g.,UIGravityBehavior * gravity = [[UIGravityBehavior alloc] init];
[animator addBehavior:gravity];
e.g.,UICollisionBehavior * collider = [[UICollisionBehavier alloc] init];
[animator addBehavior:collider];



向UIDynamicBehavior中添加UIDynamicItems:


id <UIDynamicItem> item1 = ...;
id <UIDynamicItem> item2 = ...;
[gravity addItem:item1];
[collider addItem:item1];
[gravity addItem:item2];



以上Items必须实现了UIDynamicItem协议:


@protocol UIDynamicItem
@property (readonly) CGRect bounds;
@property (readwrite) CGPoint center;
@property (readwrite) CGAffineTransfrom transform;
@end



UIView 实现了这个协议。



如果你在动画运行时修改了center或者transform,你必须调用UIDynamicAnimator的


-(void)updateItemUsingCurrentState:(id <UIDynamicItem>)item;



Behaviors


UIGravityBehavior


@property CGFloat angle;
@property CGFloat magnitude; // 1.0 is 1000 point/s/s



UICollisionBehavior


@property UiCollisionBehaviorMode collisionMode; // Items,Boundaries,Everything(default).
-(void)addBoundaryWithIdentifier:(NSString *)identifier forPath:(UIBezierPath *)path;
@property BOOL translatesReferenceBoundsIntoBoundary;



UIAttachmentBehavior


-(instancetype)initWithItem:(id <UIDynamicItem>item attachedToAnchor:(CGPoint)anchor;
-(instancetype)initwithItem:(id <UIDynamicItem>i1 attachedToItem:(id <UIDynamicItem>)i2;
-(instancetype)initWithItem:(id <UIDynamicItem>item offsetFromCenter:(CGPoint)offset...
@property (readwrite) CGFloat lenght; // distance between attached things(settable!)



也可以设置震动的阻尼和频率


@property (readwrite)CGPoint anchorPoint; //可以在任何时候重置



UISnapBehavior


-(instancetype)initWithItem:(id <UIDynamicItem>item snapToPoint:(CGPoint)point;



想象一下一个item移动到一个新位置时四周绑上了四根弹簧,


你可以使用 @property CGFloat damping; 属性来控制这“四根弹簧”的阻尼系数。



UIPushBehavior


@property UIPushBehaviorMode mode; //连续的或者瞬间的
@property CGVector pushDirection;     
@property CGFloat magnitude/angle; //magnitude 1.0 moves a 100*100 view at 100 pts/s/s



UIDynamicItemBehavior


控制物体再被其他行为影响下的表现(行为)。


任何添加到这个行为的item都会被影响到。


@property BOOL allowsRotation;
@property BOOL friction;
@property BOOL elasticity;
@property CGFloat density;



也可以获取item的信息:


-(CGPoint)linearVelocityForItem:(id <UIDynamicItem>item;
-(CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;



UIDynamicItemBehavior的行为表现比较复杂,如果你要使用多个UIDynamicItemBehavior行为,


你最好要知道自己在干什么。



UIDynamicBehavoir


是behavior的父类,你可以通过混合其他behavior来创建自己的子类。


通常你需要重写 init/addItems/removeItem方法。


-(void)addChildBehavior:(UIDynamicBehavior *)behavior;


这个是封装其他物理行为组合的好方法,


你也可能需要增加一些api来帮助你的子类来配置它的孩子(behavior)。



所有的behavior都知道自己属于哪个UIDynamicAnimator,


同一时间它们只能属于一个UIDynamicAnimator:


@property UIDynamicAnimator * dynamicAnimator;


如果它的animator发生了变化,behavior将会受到以下消息:


-(void)willMoveToAnimator:(UIdynamicAnimator *)animator;



UIDynamicBehavior的action属性


这个属性是一个block,如果设置了这个属性,这个block会在每次behavior被应用时调用


@property (copy) void (^action)(void);



你可以设置这个block来做任何事情,但是它会被调用很多次,所以尽量让他有效率的运行。


如果这个action引用了behavior内部的属性,请注意内存循环引用问题!