美文网首页
动画基础

动画基础

作者: wpf_register | 来源:发表于2016-08-16 18:20 被阅读29次

    某种意义 上苹果已经提供了优美简洁的UIView接口,对简单需求没必要处理CALayer,因为苹果已经通过UIView 的高级API 间接地使得动画变得很简单。
    但简单就不可避免地带来灵活上的缺陷,UIView 没有暴露CALayer的功能:

    1. 阴影,圆角,带颜色的边框
    2. 3D 变换
    3. 非矩形范围
    4. 透明遮罩
    5. 多级非线性动画

    基础属性

    UIImage *image = [UIImage imageNamed:@"1.jpg"];
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(0, 0, 300, 400);
    [self.view.layer addSublayer:layer];
    self.myLayer = layer;
    
    //1.contents 属性(id 类型)
    //image.CGImage 返回一个CGImageRef 指向CGImage结构的指针
    //CGImageRef 不是Cocoa对象,而是一个Core Foundation 类型,需要 __bridge转换
    layer.contents = (__bridge id)image.CGImage;
        
    //2. imageView图片有contentMode 属性设置图片填充方式
    layer.contentsGravity =    ;//不被拉伸
        
    //3. maskToBounds 相当于 clipsToBounds 属性来设置边界
    //默认情况下,UIView 和 CALayer 都会绘制走出边界的内容或子视图
        
    //4. contentsRect 允许我们在图层边框里显示寄宿图的一个子域
    //它使用单位坐标(0-1),是一个相对值,是相对于寄宿图的尺寸而言
    //这个属性可以将加载的一张图片,切成多张图片
    layer.contentsRect = CGRectMake(0.4, 0.2, 0.3, 0.3);
        
    //5. UIView 有三个布局属性 frame,bounds,center
    //CALayer 有三个布局属性 frame,bounds,position
    //frame 是外部坐标,bounds 是内部坐标
    //当操纵视图的 frame,实际上是在改变位于视图下方 CALayer 的 frame
    //当视图旋转后,其frame 与 bounds 一般会不一致。因为frame 代表了覆盖在
    //图层旋转后整个轴对齐的矩形区域。
        
    //6. 锚点
    //anchorPoint默认居中(0.5,0.5),可以理解为移动图层的把柄
    //可以通过移动锚点来改变 frame,锚点改变后,其旋转中心点也改变
        
    //7. conrnerRadius属性控制图层的曲率,只影响背景颜色而不影响子视图
    //maskToBounds 设成 YES,才会有截取
        
    //borderColor 设置边框颜色
    //borderWidth 设置边框粗细
        
    //8. shadowColor 阴影颜色
    //shadowOffset 阴影方向及距离
    //shadowRadius 阴影模糊度
    //shadowPath 阴影路径
    //注意:开启了masksToBounds 属性,越界全被截剪,阴影则无法显示
        
    //9. mask 属性本身也是一个CALayer类型
    //opacity 与 alpha 相似,都会影响子图层。
        
    //10. 当有多个子视图时,由于透明度叠加造成效果很不理想。
    //shouldRasterize 属性会将多个图层整合成整体图片然后设置透明度
    //self.myLayer.shouldRasterize = YES;
        
        
    //11. 变换
    //UIView   transform 属性,CGAffineTransform 类型(二维坐标系)
    //CALayer  transform 属性,CATransform3D 类型 (三维坐标第)
    //         affineTransform 属性,CGAffineTransform类型
        
    //layer.affineTransform = CGAffineTransformMakeRotation(M_PI/4);
        
    //混合变换
    /*
        CGAffineTransform transform = CGAffineTransformIdentity;//初始空值
        transform = CGAffineTransformScale(transform, 0.5, 0.5);
        transform = CGAffineTransformRotate(transform, M_PI/4);
        transform = CGAffineTransformTranslate(transform, 10, 30);
        layer.affineTransform = transform;
    */
    //或者
    //CGAffineTransformConcat(transform, transform);
        
    //旋转
    //基于最初的位置旋转
    //self.myLayer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
    //基于给定的transform 旋转
    //self.myLayer.transform = CATransform3DRotate(self.myLayer.transform, M_PI, 0, 1, 0);
    
    //**********透视效果,默认通过 m34 来改变*************
    //CATransform3D transform = CATransform3DIdentity;
    //transform.m34 = -1.0/500; //(500-1000是一个比较和适的值)
    //transform = CATransform3DRotate(transform, M_PI_4, 1, 0, 0);
    //layer.transform = transform;
        
    //12. 背面,当视图旋转后背面不会被绘制
    //self.myLayer.doubleSided = NO;
    

    CATransition (过渡动画)

    • CATransition动画可以实现别样的轮播图动效
    - (void)transitionAnimation{
        
        CATransition *transition = [CATransition animation];
        transition.fillMode = kCAFillModeForwards;
        transition.removedOnCompletion = YES;
        transition.startProgress = 0.0;
        transition.endProgress = 1.0;
        transition.duration = 1.0;
        transition.type = kCATransitionMoveIn;
        
        
        /*
         私有接口(慎用)
         cube   立体翻转
         oglFlip 翻转
         suckEffect 收缩效果
         rippleEffect 水滴波纹
         pageCurl   翻页
         pageUnCurl
         cameralIrisHollowOpen 摄像头打开效果
         cameraIrisHollowClose  关闭效果
         
         */
        
        /*
         公有接口
         kCATransitionFade 淡出效果
         kCATransitionMoveIn 新视图移到旧视图上
         kCATransitionPush  新视图推出旧视图
         kCATransitionReveal 移开旧视图显示新视图
         */
        
        transition.subtype = kCATransitionFromLeft;
        
        /*
         kCATransitionFromRight
         kCATransitionFromLeft
         kCATransitionFromTop
         kCATransitionFromBottom
         */
        
        
        [self.imageView.layer addAnimation:transition forKey:@"transition"];
        [self setNewImage];
    }
    

    只要用手势或计时器回调下面方法即可实现轮播效果

    - (void)setNewImage{
        static int i = 5;
        i++;
        int imageIndex = i%5;
        NSString *imageName = [NSString stringWithFormat:@"%d.jpg",imageIndex];
        [self.imageView setImage:[UIImage imageNamed:imageName]];
    }
    

    或者

    [UIView transitionWithView:_imageView
                          duration:1.0
                           options:UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{
     // [self.imageView setFrame:CGRectMake(0, 0, 300, 300)];            
         [self setNewImage];
                        } completion:nil];
    
    
    • CATransition动画实现简单的转场效果
    // 在window上执行CATransition, 即可在ViewController转场时执行动画。
    [self.view.window.layer addAnimation:animation forKey:@"kTransitionAnimation"];
    PresentedViewController *presentedVC = [[PresentedViewController alloc] init];
    [self presentViewController:presentedVC animated:NO completion:nil];
    
    • tabBarViewController 可以添加过渡效果
    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
        UIViewController *viewController1 = [[FirstViewController alloc]initWithNibName:@"FirstViewController" bundle:nil];
        UIViewController *viewController2 = [[SecondViewController alloc]initWithNibName:@"SecondViewController" bundle:nil];
        
        viewController2.title = @"第一";
        viewController1.title = @"第二";
        self.tabBarController = [[UITabBarController alloc]init];
        self.tabBarController.viewControllers = @[viewController1,viewController2];
        self.tabBarController.delegate = self;
        self.window.rootViewController = self.tabBarController;
        [self.window makeKeyAndVisible];
        
        
        return YES;
    }
    
    -(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
        CATransition *transition = [CATransition animation];
        transition.type = kCATransitionFade;
        transition.duration= 3; //3秒时间过渡效果会明显一些
        [self.tabBarController.view.layer addAnimation:transition forKey:@"transition"];
    }
    
    

    CAKeyframeAnimation

    - (void)keyFrameAnimation{
        
          CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
          UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.view.center
                                                              radius:100
                                                          startAngle:0
                                                            endAngle:2 * M_PI
                                                           clockwise:YES];//顺时针方向
          keyframeAnimation.path = path.CGPath;//UIKit框架转CG框架
          keyframeAnimation.duration = 3;
          keyframeAnimation.repeatCount = 1;
          keyframeAnimation.fillMode = kCAFillModeForwards;
          keyframeAnimation.removedOnCompletion  = NO;
          keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
          //这个属性很有意思。
          keyframeAnimation.rotationMode = KCAAnimationRotateAuto;
          //*******设置value后会覆盖path********//
          //KeyframeAnimation.values = @[ ];
          [self.layer addAnimation:keyframeAnimation forKey:@"keyframeAnimation"];
     }
    
    - (void)addShakeAnimationForView:(UIView *)view withDuration:(NSTimeInterval)duration {
        
        CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
        CGFloat currentTx = view.transform.tx;
        
        animation.delegate = self;
        animation.duration = duration;
        animation.values = @[ @(currentTx), @(currentTx + 10), @(currentTx-8), @(currentTx + 8), @(currentTx -5), @(currentTx + 5), @(currentTx) ];
        animation.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1) ];
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        [self.layer addAnimation:animation forKey:@"keyframeAnimation"];
    }
    

    CABasicAnimation

    /**
     *  CABsicAnimation 的实例对象只是一个数据模型,
     *  addAnimation:forKey只是将对象的copy,所以也可以添加到另外一个layer上
     *
     */
    
    /**
     *  为什么动画会返回原状态
     *  添加动画时,真正移动的并不是视图本身,而是presentation Layer的一个缓存
     *  动画开始,presentation Layer开始移动,原始layer隐藏
     *  动画结束,presentation layer开始移除,原始layer显示
     */
    
    - (void)basicAnimation{
        
        //旋转动画
        CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
        rotateAnimation.duration = 3.0;
        rotateAnimation.repeatCount = 100;
        rotateAnimation.autoreverses = YES;
        rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
        rotateAnimation.toValue = [NSNumber numberWithFloat:6*M_PI];
        [self.layer addAnimation:rotateAnimation forKey:@"rotate"];
       
        //放大 缩小
        CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        scaleAnimation.duration = 3.0;
        scaleAnimation.repeatCount = 1;
        scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
        scaleAnimation.toValue = [NSNumber numberWithFloat:3];
        //动画结束后保持移动后的位置
        scaleAnimation.removedOnCompletion = NO;
        scaleAnimation.fillMode = kCAFillModeForwards;
        //设置动画速率
        scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        /**
         *  kCAMediaTimingFunctionLinear
         *  kCAMediaTimingFunctionEaseIn  开始慢,后来快
         *  kCAMediaTimingFunctionEaseOut
         */
        
       [self.layer addAnimation:scaleAnimation forKey:@"scale"];
        //设置代理可以监测动画开始和结束时的动作
        scaleAnimation.delegate = self;
        
        
        //平移动画
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
        animation.duration = 3.0;
        animation.autoreverses = YES;
        animation.repeatCount = 100;
        animation.fromValue = [NSValue valueWithCGPoint:_layer.position];
        CGPoint toPoint = _layer.position;
        toPoint.x = toPoint.x+180;
        animation.toValue = [NSValue valueWithCGPoint:toPoint];
        [self.layer addAnimation:animation forKey:@"move"];
        
    }
    

    UIView动画

    • 动画使用
    3D变换可将图层顺序更改
    动画中更改使用transform可以快速方便地改变frame 
     [UIView animateWithDuration:0.5 animations:^{
            self.testView.layer.transform = CATransform3DMakeTranslation(10, 10, 1);
        } completion:nil];
    [UIView animateWithDuration:0.5 animations:^{
            self.testView.transform = CGAffineTransformMakeTranslation(10, 10);
        } completion:nil];
    

    -(void)normalAnimation{
        [UIView animateWithDuration:2
                              delay:1
                            options:UIViewAnimationOptionRepeat
                         animations:^{
                             [UIView setAnimationRepeatCount:3];
                             [UIView setAnimationRepeatAutoreverses:YES];
                             self.redView.center = self.view.center;
                         }
                         completion:^(BOOL finished){
                             NSLog(@"finished--%d",finished); }
         ];  
    }
    

    UIViewAnimationOptions op = UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState;
    [UIView animateWithDuration:0.1
                            delay:0 
                          options:op
                       animations:^{
                //view缩小
                [_view.layer setValue:@(0.5) forKeyPath:@"transform.scale"];
            } completion:^(BOOL finished) {
              
                [UIView animateWithDuration:0.1 delay:0 options:op animations:^{
                // view放大
                 [_view.layer setValue:@(1.08) forKeyPath:@"transform.scale"];
                } completion:^(BOOL finished) {
                           [UIView animateWithDuration:0.1 delay:0 options:op animations:^{
                           //view恢得原样
                            [_view.layer setValue:@(1) forKeyPath:@"transform.scale"];
                    } completion:NULL];
                }];
            }];
    
    • spring动画
    -(void)springAnimation{
        
        [UIView animateWithDuration:1
                              delay:0
             usingSpringWithDamping:100//类似弹簧振动效果,越小越明显
              initialSpringVelocity:10 //初始速度
                            options:UIViewAnimationOptionCurveLinear
                         animations:^{
                             [UIView setAnimationRepeatCount:5];
                             self.redView.frame = CGRectMake(50, 200, 100, 100);
                         }
                         completion:^(BOOL finished) {
                             
                         }];
    }
    
    • 关键帧动画
    -(void)keyFrameAnimationView{
        [UIView animateKeyframesWithDuration:6
                                       delay:0.0
                                     options:UIViewKeyframeAnimationOptionLayoutSubviews
                                  animations:^{
                                      
                                      [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.3 animations:^{
                                          self.redView.center = self.view.center;
                                      }];
                                      [UIView addKeyframeWithRelativeStartTime:0.3 relativeDuration:0.3 animations:^{
                                          self.redView.backgroundColor = [UIColor orangeColor];
                                      }];
                                      [UIView addKeyframeWithRelativeStartTime:0.6 relativeDuration:0.4 animations:^{
                                          CGRect rect= self.redView.frame;
                                          rect.size.width +=rect.size.width;
                                          rect.size.height +=rect.size.height;
                                          self.redView.frame =rect;
                                      }];
                                      //relativeStartTime
                                      //relativeDuration  都是相对时间,占总时间的占比
                                      
                                  } completion:^(BOOL finished) {
                                      NSLog(@"动画结束");
                                  }];
    }
    
    

    UIView动画停止

    - (void)startAnimation {
     [UIView animateWithDuration:1.0
                           delay:0.0
                         options:UIViewAnimationOptionCurveLinear |
                                 UIViewAnimationOptionAllowUserInteraction
                      animations:^(void) {
                             //动画
                    } completion:^(BOOL finished) {
    
           if(!self.canceled) {
            __weak id weakSelf = self;
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                         [weakSelf startAnimation];
                    }];
             }
          }];
    }
    

    相关文章

      网友评论

          本文标题:动画基础

          本文链接:https://www.haomeiwen.com/subject/oappsttx.html