zoukankan      html  css  js  c++  java
  • iOS动画总结

    iOS--Animation总结

    UIKit框架中

    1.UIImageView里的序列帧动画

    • 将序列帧动画图片存入imageView.animationImages数组中

    示例:

    NSMutableArray * array = [NSMutableArray array];
    
    for (int i = 1; i < 6; i++) {
        //将图片存入数组
        NSString * string = [NSString stringWithFormat:@"hehua0%d",i];
        UIImage * image = [UIImage imageNamed:string];
        [array addObject:image];
    }
    
    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    //设置动画图片
    self.imageView.animationImages = array;
    //动画时间
    self.imageView.animationDuration = 1;
    //动画播放重复次数,值为0时,无限循环
    self.imageView.animationRepeatCount = 0;
    //开始动画
    [self.imageView startAnimating];
    //结束动画
    [self.imageView stopAnimating];
    
    • 播放GIF动画

    可为UIImageView添加类别来实现方法

    如+ (UIImageView *)imageViewWithGIFFile:(NSString *)file frame:(CGRect)frame;

    导入头文件<ImageIO/ImageIO.h>和<CoreText/CoreText.h>

       /**
       * ARC下需要手动管理内存的有(Core)
       *CT开头,例如:CTRunRef
       *CF开头,例如:CTFrameRef
       *CG开头,例如:CGImageSourceRef
       */
    
      @implementation UIImageView (GIF)
    
      + (UIImageView *)imageViewWithGIFFile:(NSString *)file frame:(CGRect)frame
      {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
        // 加载gif文件数据
        NSData *gifData = [NSData dataWithContentsOfFile:file];
        
        // GIF动画图片数组
        NSMutableArray *frames = nil;
        // 图像源引用
        CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)gifData, NULL);
        // 动画时长
        CGFloat animationTime = 0.f;
        
        if (src) {
            // 获取gif图片的帧数
            size_t count = CGImageSourceGetCount(src);
            // 实例化图片数组
            frames = [NSMutableArray arrayWithCapacity:count];
            
            for (size_t i = 0; i < count; i++) {
                // 获取指定帧图像
                CGImageRef image = CGImageSourceCreateImageAtIndex(src, i, NULL);
                
                // 获取GIF动画时长
                NSDictionary *properties = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(src, i, NULL);
                NSDictionary *frameProperties = [properties objectForKey:(NSString *)kCGImagePropertyGIFDictionary];
                NSNumber *delayTime = [frameProperties objectForKey:(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
                animationTime += [delayTime floatValue];
                
                if (image) {
                    [frames addObject:[UIImage imageWithCGImage:image]];
                    CGImageRelease(image);
                }
            }
            
            CFRelease(src);
        }
        
        [imageView setImage:[frames objectAtIndex:0]];
        [imageView setBackgroundColor:[UIColor clearColor]];
        [imageView setAnimationImages:frames];
        [imageView setAnimationDuration:animationTime];
        [imageView startAnimating];
        
        return imageView;
      }
    
    

    2.UIView动画

    • 简单动画

        //开始动画
        [UIView beginAnimations:@"自定义动画名称" context:nil];
        //延迟2秒执行
        //[UIView setAnimationDelay:2];
        //设置动画时间
        [UIView setAnimationDuration:1];
        //设置动画代理
        [UIView setAnimationDelegate:self];
        //将要开始动画
        [UIView setAnimationWillStartSelector:@selector(要开始动画时执行)];
        //已经结束动画
        [UIView setAnimationDidStopSelector:@selector(结束动画执行)];
        //设置动画的速度变化
        [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
        //设置重复次数
        //[UIView setAnimationRepeatCount:3];
        //动画的反转
        //[UIView setAnimationRepeatAutoreverses:YES];
        
        //设置UIView的位置变化,大小变化,透明度
        
        //    self.imageView.alpha = 0;
        //    self.testView.backgroundColor = [UIColor redColor];
        //
        //    distantce += 20;
        //
        //    self.testView.frame = CGRectMake(distantce, 0, 100, 100);
        
        //拉伸
        // self.testView.transform = CGAffineTransformMakeScale(1.5, 1.5);
        //平移
        //    self.testView.transform = CGAffineTransformMakeTranslation(100, 100);
        //    self.testView.transform = CGAffineTransformTranslate(self.testView.transform, 20, 0);
        
        //旋转
        //self.testView.transform = CGAffineTransformMakeRotation(M_PI_2);
        //self.testView.transform = CGAffineTransformRotate(self.testView.transform, M_PI_4/2);
        
        //提交动画
        [UIView commitAnimations];
    
    • 转场动画

    (1)在一个UIView上添加两个imageView,然后设置动画

     [UIView beginAnimations:@"transition" context:nil];
    
     [UIView setAnimationDuration:2];
        
      //设置转场动画 
     [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.contentView cache:YES];
        
     [self.contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
        
     [UIView commitAnimations];
        
    

    (2)UIView block转场动画

    secondView -> firstView

    这个方法会作用于fromView的父视图,用于切换两个view,通过执行这个方法,会将formView从其父视图上移除,将toView重新粘在其父视图上,展现一个动画效果。

    [UIView transitionFromView:self.secondView toView:self.firstView duration:2 options:UIViewAnimationOptionTransitionCurlUp completion:^(BOOL finished) {
            
     }];
        
    

    转场动画的block实现

     [UIView transitionWithView:self.contentView duration:2 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
        //1.该方法可以实现两个页面的来回切换
        [self.contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
        
        //2.该方法只能实现一次转场动画
    //  [self.firstView removeFromSuperview];
    //  [self.contentView addSubview:self.secondView];
            
            
        } completion:^(BOOL finished) {
            
        }];
    
    
    • UIView的block动画

    (1)简单block动画的实现

      例1 图片的透明度变化动画
      
       //Duration动画时间 animations里是要到达的状态,completion里是动画完成之后的代码块
        
     [UIView animateWithDuration:1 animations:^{
          self.imageView.alpha = 0;
        } completion:^(BOOL finished) {
                
            [UIView animateWithDuration:1 animations:^{
                
                self.imageView.alpha = 1;
    
            } completion:^(BOOL finished) {
               
            }];
      }];
    
    
    例2 图片的旋转变化动画
    
    [UIView animateWithDuration:1 animations:^{
            
            self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI_2);
            
        } completion:^(BOOL finished) {
            
            [UIView animateWithDuration:1 animations:^{
                //下面是实现图片旋转一定度数后返回原位置的两种方法
                self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, -M_PI_2);
                
                //CGAffineTransformIdentity恢复最初状态
    //            self.imageView.transform = CGAffineTransformIdentity;
    
            }];
            
        }];
    
    
    例3 增加了动画延迟
    
        [UIView animateWithDuration:1 delay:2 options:UIViewAnimationOptionCurveEaseOut animations:^{
            self.imageView.backgroundColor = [UIColor grayColor];
        } completion:^(BOOL finished) {
            
        }];
    
    
    

    (2) 带弹性效果的动画

        //Damping 弹力 0 ~ 1  
        //SpringVelocity 弹簧初速度
        
       [UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:10 options:UIViewAnimationOptionCurveLinear animations:^{
    
            self.imageView.frame = CGRectMake(200, 100, 100, 100);
            
        } completion:^(BOOL finished) {
            
        }];
    
    

    (3)关键帧动画

        [UIView animateKeyframesWithDuration:3.0 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
            
            [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1/6.0 animations:^{
                self.imageView.backgroundColor = [UIColor redColor];
            }];
            
            [UIView addKeyframeWithRelativeStartTime:1/6.0 relativeDuration:3/6.0 animations:^{
                self.imageView.backgroundColor = [UIColor blueColor];
            }];
            
            [UIView addKeyframeWithRelativeStartTime:4/6.0 relativeDuration:2/6.0 animations:^{
                self.imageView.backgroundColor = [UIColor orangeColor];
            }];
            
            
        } completion:^(BOOL finished) {
            
        }];
    
    
    

    QuartzCore框架中

    3.CALayer的隐式动画

    • 什么时候使用CALayer,什么时候使用UIView?

      当视图需要响应时使用UIView,仅作为展示使用CALayer.

      隐式动画只存在于CALayer的子层上

        CALayer * layer = [CALayer layer];
        
        layer.backgroundColor = [UIColor greenColor].CGColor;
        
        layer.frame = CGRectMake(100, 100, 100, 100);
    
        [self.view.layer addSublayer:layer];
    
    
        //当执行layer变化语句时,默认有动画,即隐式动画
        _layer.frame = CGRectMake(100, 100, arc4random_uniform(100), arc4random_uniform(100));
    
    

    4.核心动画Core Animation

    ?核心动画和UIView动画的区别

     核心动画一切都是假象,并不会真实的改变图层的属性值,如果以后做动画的时候,不需要与用户交互,通常用核心动画(转场)
    
     UIView动画必须通过修改属性的真实值,才有动画效果
    

    CAAnimation是一个抽象类,mac,iOS 通用,遵循了CAMediaTiming协议和CAAction协议!我们不要直接使用CAAnimation类,而是使用其子类:

    具体可看 http://www.henishuo.com/caanimation-indtroduce-in-detail/

    CAAnimation(父类) -> CAPropertyAnimation 属性动画 -> (CABasicAnimation 基础动画 ,CAKeyframeAnimation 关键帧动画)

    CAAnimation -> CAAnimationGroup 动画组

    • CABasicAnimation基础动画

        //创建基础动画
        CABasicAnimation * basic = [CABasicAnimation animation];
        //动画路径
        basic.keyPath = @"position";
        
        //绝对距离
        //设置初始状态
    //    basic.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        //终止状态
    //    basic.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)];
        
        //动画距离(相对距离)
        //basic.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
        
        //动画的初始和结束的模式 fillMode和removedOnCompletion要配合使用
        basic.fillMode = kCAFillModeForwards;// @"forwards";
        //动画完成在layer中删除
        basic.removedOnCompletion = NO;
        
        //如果初始状态就是当前动画未执行的位置
        
        //动画时间
        basic.duration = 1;
        
        //动画的速度变化 eg:kCAMediaTimingFunctionEaseIn越来越快
        basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        //?
        //animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.5 :0 :0.9 :0.7];
    
        
        //添加动画
        [_animationView.layer addAnimation:basic forKey:@"basic"];
    
    
    
    • CAKeyframeAnimation 关键帧动画

        //创建关键帧动画
        CAKeyframeAnimation * keyframe = [CAKeyframeAnimation animation];
        
        keyframe.keyPath = @"position.x";
        
        //设置关键帧的位置
        keyframe.values = @[@0,@10,@-10,@10,@0];
    
        //设置关键帧的时间
        keyframe.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
        
        //无需设置起始位置
        keyframe.additive = YES;
        
        //calculationMode设置加速度,kCAAnimationPaced保持恒定的加速度,如果设置calculationMode,keyTimes失效
        keyframe.calculationMode = kCAAnimationPaced;
        
        //设置时间
        keyframe.duration = 0.5;
        
        [_animationView.layer addAnimation:keyframe forKey:@"keyframe"];
    
    
    利用贝塞尔
    
        UIView * v = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 30, 30)];
        v.backgroundColor = [UIColor grayColor];
        [self.view addSubview:v];
    
        UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 300, 300)];
        
        //创建关键帧动画
        CAKeyframeAnimation * keyframe = [CAKeyframeAnimation animation];
        
        keyframe.keyPath = @"position";
        
        keyframe.path = path.CGPath;
        
        //设置时间
        keyframe.duration = 2;
        
        //重复次数
        keyframe.repeatCount = HUGE_VALF; //MAXFLOAT;
        
        [_animationView.layer addAnimation:keyframe forKey:@"keyframe"];
    
    
    • CAAnimationGroup动画组

        CABasicAnimation * basic1 = [CABasicAnimation animation];
        basic1.keyPath = @"transform.scale";
        basic1.toValue = @(arc4random_uniform(5));
        basic1.duration = 0.5;
        basic1.removedOnCompletion = NO;
        basic1.fillMode = @"forwards";
    //    [self.animationView.layer addAnimation:basic1 forKey:@"aaa"];
        
        CABasicAnimation * basic2 = [CABasicAnimation animation];
        basic2.keyPath = @"transform.rotation";
        basic2.toValue = @(arc4random_uniform(M_PI));
        basic2.duration = 0.5;
        basic2.beginTime = 0.5;
        
    //    [self.animationView.layer addAnimation:basic2 forKey:nil];
    
        CAAnimationGroup * group = [CAAnimationGroup animation];
        
        group.duration = 1;
        group.removedOnCompletion = NO;
        group.fillMode = @"forwards";
    
        group.animations = @[basic1,basic2];
        
        [self.animationView.layer addAnimation:group forKey:nil];
    
    
    • CATransition过渡动画

    设置视图变化时的动画效果

    • 1.#define定义的常量

      • kCATransitionFade 交叉淡化过渡

      • kCATransitionMoveIn 新视图移到旧视图上面

      • kCATransitionPush 新视图把旧视图推出去

      • kCATransitionReveal 将旧视图移开,显示下面的新视图

    • 2.用字符串表示

      • pageCurl 向上翻一页

      • pageUnCurl 向下翻一页

      • rippleEffect 滴水效果

      • suckEffect 收缩效果,如一块布被抽走

      • cube 立方体效果

      • oglFlip 上下翻转效果

        CATransition * transition = [CATransition animation];
        transition.type = @"suckEffect";
        transition.subtype = @"fromLeft";
        transition.duration = 2;
        [self.imageView.layer addAnimation:transition forKey:nil];
    
    

    //CADisplayLink,selector每秒钟默认调用60次。

    //CADisplayLink和NSTimer区别:CADisplayLink用来做绘图,重绘。NSTimer用于计时,重复调用。

     //创建CADisplayLink
       self.displaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleAction:)];
       
       //调用次数 = 60 / frameInterval
    //    self.displaylink.frameInterval = 3;
       
       //将CADisplayLink放入RunLoop里
       [self.displaylink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    

    Facebook POP动画

    • poping开源库

    POP比较好的一点是保留了动画结束后的状态,通过block回调。使用POPAnimatableProperty 可以快速添加基本动画,也可以自定义属性动画。

    ---弹性动画---
    
    - (void)spring{
    
        POPSpringAnimation* framePOP = [POPSpringAnimation animationWithPropertyNamed:kPOPViewBackgroundColor];
    
        framePOP.springSpeed = 10.f;
    
        framePOP.springBounciness = 4.f;
    
        framePOP.toValue = [UIColor greenColor];
    
        [framePOP setCompletionBlock:^(POPAnimation * anim , BOOL finsih) {
    
            if (finsih) {
    
                NSLog(@"view.frame = %@",NSStringFromCGRect(view.frame));
    
            }
    
        }];
    
        [view pop_addAnimation:framePOP forKey:@"go"];
    
    }
    
    
    ---减缓动画——--
    
    - (void)Decay{
    
        POPDecayAnimation* decay = [POPDecayAnimation animationWithPropertyNamed:kPOPViewFrame];
    
    // decay.toValue = [NSValue valueWithCGRect:CGRectMake(200, 400, 100, 100)];
    
        decay.velocity = [NSValue valueWithCGRect:CGRectMake(200, 300, 100, 100)];
    
        [view pop_addAnimation:decay forKey:@"go"];
    }
    
    
    ---基本动画---
    
    -(void)basic{
    
        POPBasicAnimation* basicAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerCornerRadius];
    
        basicAnimation.toValue = [NSNumber numberWithFloat:CGRectGetHeight(view.frame)/2.];
    
        basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    // basicAnimation.duration = 3.f;
    
        [basicAnimation setCompletionBlock:^(POPAnimation * ani, BOOL fin) {
    
            if (fin) {
    
                NSLog(@"view.frame = %@",NSStringFromCGRect(view.frame));
    
    // POPBasicAnimation* newBasic = [POPBasicAnimation easeInEaseOutAnimation];
    
    // newBasic.property = [POPAnimatableProperty propertyWithName:kPOPLayerCornerRadius];
    
    // newBasic.toValue = [NSNumber numberWithFloat:0];
    
    // [view.layer pop_addAnimation:newBasic forKey:@"go"];
    
            }
    
        }];
    
        [view.layer pop_addAnimation:basicAnimation forKey:@"frameChange"];
    
    
    ---组合动画---
    
    -(void)group
    {
    
        view.transform = CGAffineTransformMakeRotation(M_PI_2/3);
    
        POPBasicAnimation* spring = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    
        spring.beginTime = CACurrentMediaTime();
    
        spring.duration = .4f;
    
        spring.fromValue = [NSNumber numberWithFloat:-100.f];
    
        spring.toValue = [NSNumber numberWithFloat:CGRectGetMinY(view.frame) + 80];
    
        [spring setCompletionBlock:^(POPAnimation * ani, BOOL fin) {
    
        }];
    
        POPBasicAnimation* basic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation];
    
        basic.beginTime = CACurrentMediaTime();
    
        basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
        basic.toValue = [NSNumber numberWithFloat:-M_PI_4];
    
        basic.duration = .4f;
    
        POPBasicAnimation* rotation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation];
    
        rotation.beginTime = CACurrentMediaTime() + .4f;
    
        rotation.toValue = [NSNumber numberWithFloat:0.f];
    
        rotation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
        rotation.duration = .25f;
    
        POPBasicAnimation* donw = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    
        donw.beginTime = CACurrentMediaTime() + 0.4f;
    
        donw.toValue = [NSNumber numberWithFloat:CGRectGetMinY(view.frame)];
    
        donw.duration = .25f;
    
        donw.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
        [view.layer pop_addAnimation:spring forKey:@"spring"];
    
        [view.layer pop_addAnimation:basic forKey:@"basic"];
    
        [view.layer pop_addAnimation:donw forKey:@"down"];
    
        [view.layer pop_addAnimation:rotation forKey:@"rotation"];
    
    }
    
    
    
  • 相关阅读:
    android:id="@android:id/tabhost" 、android:id="@+id/llRoot" 、android:id="@id/llRoot" 之间的区别
    android:ellipsize的使用
    PopupWindow为什么要设置setBackgroundDrawable(new BitmapDrawable());
    android中LayoutInflater的3种使用以及getSystemService的API
    context 的理解
    Android 中this、getContext()、getApplicationContext()、getApplication()、getBaseContext() 之间的区别
    android Matrix 使用
    public private protected frientdly 作用域
    pyinstaller参数介绍以及总结
    MongoDB高级查询详细
  • 原文地址:https://www.cnblogs.com/xiaonan-net/p/5483812.html
Copyright © 2011-2022 走看看