iOS 动画实现和理解

   1、首先从整体角度说一下:从实现动画的方法上来说,可以分为2个层次,第一个UIView方法,第二个是CGAffineTransform方法,第二个是coreAnimation的方法,他们分别属于UIKit、QuartzCore框架。动画的方法很多,不先分清是属于哪个层次或框架的方法容易搞混,而且有些长得也很像,比如CGAffineTransform和CATransition。而且不同层次的方法个性不一样,分清归类后比较容易知道在什么时候用什么。下面分别从这3个方面写一下实现动画的方法。

  2、UIView方法:

       从写法上来说,UIView的方法可以分为两类,即使用+ (void)beginAnimations:(NSString *)animationID context:(void *)context 结合 + (void)commitAnimations  。还是使用block块。从效果上来说应该没有区别,而且属性设置差不多,只是使用block需要注意避免循环引用。

      以block方法为例,首先是最常用的+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;

使用:

[UIView animateWithDuration:0.5 animations:^{
            CGPoint imgCenter = _imgView.center;
            _imgView.center = CGPointMake(imgCenter.x, imgCenter.y+50);
        }];
_imgView是一个简单的图片View,这里的动画实现了图片的下移。很简单。和这个方法类似的还有3个,相比添加了一些控制动画的参数, completion:后面是一个block这个是在动画执行结束时调用的,便于在动画执行结束后接着做处理。如果不使用block实现动画,需要使用下面3个方法结合使用来实现回调:

  • + setAnimationDelegate:   //指定下面两个方法的执行对象
  • + setAnimationWillStartSelector:   //指定在动画开始时调用的方法
  • + setAnimationDidStopSelector:   
如果使用coreAnimation,动画本身是一个对象,可以使用委托,效果同上。

   使用UIView的方法可以使用几句代码实现复杂的动画,比如

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion方法,可以实现类似日历翻页效果。参数options是一个枚举,配置动画的一些属性,按效果分3部分,文档里面有意分割开了。第二部分是控制动画的速度行为,例如

UIViewAnimationOptionCurveEaseOut是指在动画结束的时候变化速度加快。第三部分是动画的效果,UIViewAnimationOptionTransitionFlipFromLeft是向左侧旋转翻转,UIViewAnimationOptionTransitionCurlUp是类似向上翻日历本一样的效果,UIViewAnimationOptionTransitionCrossDissolve是淡化当前的view然后逐渐变为目标view.但是有一点值得注意的,在flip和curl效果的时候,动画是作用在fromView的superView上面的。而且动画执行完后,fromView会从俯视图移除、释放掉,toView替代fromView原来的位置。

   使用UIView的动画方法,会自动将写在一起的动画合并一起执行,比如

[UIView animateWithDuration:4.5 animations:^{
            _imgView.alpha = 0.3;
            CGPoint imgCenter = _imgView.center;
            _imgView.center = CGPointMake(imgCenter.x, imgCenter.y+50);
        }];

这里有透明度变化和位置变化两个动画,虽然透明变化的代码在前面,但是不会等这个动画执行完了在执行下一个,会通知执行这些动画,也就是说不需要自己去组装合并这些动画。如果希望顺序执行,可以分开写两个动画,但是ios7之后给了新的方法:

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;可以实现多个动画顺序执行并且可以很好控制单个动画的时间。

3、CGAffineTransform:

   使用UIView方法实现动画,是通过更改目标View的属性来实现动画,好像是把原来一瞬间完成的事情拉长了,并且连续的执行。可以实现移动、缩放、渐变(透明度,颜色)等效果,但是想要实现旋转,貌似无法通过调节view的直观属性来实现,需要使用CGAffineTransform:

[UIView beginAnimations:nil context:nil];
     [UIView setAnimationDuration:2];
    CGAffineTransform transform  =CGAffineTransformMakeRotation(M_PI);
    [self.imgView setTransform:transform];
    [UIView commitAnimations];
以上实现imgView旋转180度的效果,CGAffineTransform还是需要配合UIView的动画方法来使用,它提供了动画执行的方式。CGAffineTransform本身不是动画类也不提供动画方法,只是和UIView的动画方法结合比较简洁。CGAffineTransform有3种,即

Rotation旋转、Scale缩放和Translation移动。

4、coreAnimation类和方法:

     coreAnimation的方法更底层,可以对动画进行更多的设定和控制。

    首先是CAAnimation类,是动画抽象类,由它派生CAAnimationGroup和CAPropertyAnimation,CAAnimationGroup是合并多个动画时使用的组动画,类似于cocos2d里面的CCActionSequence的作用。CAPropertyAnimation又派生CAKeyframeAnimation和

CABasicAnimation。实现动画主要就是这两个类。CAKeyframeAnimation用来实现关键帧动画,CABasicAnimation则通过一个键值来制定动画类型。

   (1)CAKeyframeAnimation:

       首先什么是关键帧动画,百度百科http://baike.baidu.com/view/1336186.htm?fr=aladdin

  在这里,我的理解是给定一系列关键的节点,这些节点指定了执行动画的view的状态,然后目标view在这些节点上连续的切换。

使用CAKeyframeAnimation很好的一个方面是用来实现一个路径动画,即指定某个view按特定路径进行运动,比如点击商品添加进购物车,需要商品划一道曲线然后落到购物车的位置。

      

CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        CGMutablePathRef path = CGPathCreateMutable();
        
        CGPoint center = self.imgView.center;
        CGPathMoveToPoint(path, nil, center.x+20, center.y-20);
        CGPathAddCurveToPoint(path, nil, 0, 0, 250, 600, 320, 500);
       
        animation.path = path;    //可以使用CGMutablePathRef来确定动画的路径,也可以使用values来确定,values是一系列关键的点;
        animation.duration = 2.00;
        animation.beginTime = 0;   //用于多组动画播放的相对时间
        animation.repeatCount = 0;
        animation.removedOnCompletion = NO;           //在动画结束后,是否将animation从layer上移除,如果移除,那么就会回到最初的状态,默认是YES;
       // animation.autoreverses = YES;
        animation.fillMode = kCAFillModeForwards;     //上面设置了no,之后还要有这里设置一下,否则图片还是会回到最初的状态
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        //NSArray * keyTimes = @[@0,@0.1,@0.2,@0.3,@1];
        //animation.keyTimes = keyTimes;      //这个比较好用,就是每个点(动画里面的关键位置,比如values里面的每个点,在这个例子中就是rect的四角)所在的时间点(是时间点,不是所用的时间)
        
        [self.imgView.layer addAnimation:animation forKey:@"position"];   //这是最后关键的一步,将动画加入到view的layer里面。 
        CGPathRelease(path);
   以上是让self.imgView按一个曲线路径进行运动的动画实现,首先使用键值“position”来确定 CAKeyframeAnimation的类型,然后最重要的是给animation提供一个路径path,路径是CGMutablePathRef类型,通过CGPathCreateMutable()方法构建,而路径的具体内容和绘制曲线的方法几乎一致,了解quzrtz2D绘图之后就很容易理解路径的绘制,上面的例子就是一个贝塞尔曲线。因为路径可以任意绘制,所以想要什么样的动画运动路线都可以满足。

   除了使用路径,也可以使用values来确定,values是一系列关键的点,执行动画的view会一次移动到给定的这些关键点,形成连续的移动动画。相对UIView的方法而言,如果是相对复杂多变的移动,使用CAKeyframeAnimation会简单很多。而使用values来指定运动路径时,keyTimes属性就起作用了,它也是一个数组,对应的指定了从动画开始到相应点的时间。比如NSArray * keyTimes = @[@0,@0.1,@0.2,@0.3,@1];那么运动到第一个点的时间是总时间*0.1,运动到第二个点时的时间是总时间*0.2。

 (2)CABasicAnimation:

 CABasicAnimation * rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
        rotationAnimation.fromValue = [NSNumber numberWithFloat:0];
        rotationAnimation.toValue = [NSNumber numberWithFloat:2 * M_PI];
        rotationAnimation.removedOnCompletion = NO;
        rotationAnimation.fillMode = kCAFillModeForwards;
        rotationAnimation.duration =2.0;
        rotationAnimation.repeatCount = 0;
        //rotationAnimation.autoreverses = YES;
        rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        [rotationAnimation setDelegate:self];
        [self.imgView.layer addAnimation:rotationAnimation forKey:nil];
同样使用键值和方法 animationWithKeyPath:来构建动画对象并指定动画的类型。CABasicAnimation基本上是通过指定fromValue和toValue来确定动画执行的变化的。比如上面的例子,是执行旋转动画,然后指定的开始和结束值就是角度,所以

 rotationAnimation.fromValue = [NSNumber numberWithFloat:0];
 rotationAnimation.toValue = [NSNumber numberWithFloat:2 * M_PI];
这样动画就会瞬间切换到fromValue的状态,然后动画形式变化到tovalue状态。

所以从使用角度来说,知道使用什么键值来指定CABasicAnimation的类型以及使用什么样对应的fromValue和toValue是关键。

键值有这些:

transform.scale  缩放

bounds 大小

transform.rotation  旋转

opacity 透明度变化

shadowOffset  阴影范围

cornerRadius   圆角的大小

contents  内容变化,可以使用它以渐变方式替换imageView的图片


   然后,CAAnimation可以指定委托对象,但是这里的委托没有协议需要继承,只要指定了对象就可以响应动画的委托方法,便于在动画的执行过程中进行响应控制。

  最后,还有许多没有研究,以后有了新东西在添加。

转载于:https://www.cnblogs.com/walkingZero/p/3920519.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值