动画

E5C0948F-DC76-449C-90D9-14C7E027B9AA.png

首先我们先回顾下图中的View动画
UIView基础动画实现方式一

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//创建一个动画
    [UIView beginAnimations:nil context:nil];
    //动画延迟
    [UIView setAnimationDelay:2];
    //给动画添加代理(此代理协议可以不写,也能实现代理方法)
    [UIView setAnimationDelegate:self];
    //给动画添加方法(动画结束后执行)
    [UIView setAnimationDidStopSelector:@selector(test)];
    //动画持续时间
    [UIView setAnimationDuration:2];
    //设置动画效果是否会自动重复播放
    [UIView setAnimationRepeatAutoreverses:NO];
    //用以上动画效果,使声明好的label属性从自己原来给的布局的位置移动到下边新的位置
    self.label.frame = CGRectMake(100, 100, 100, 100);
//开始动画命令
    [UIView commitAnimations];
    
}

- (void)test{
    NSLog(@"动画结束");
}

UIView基础动画实现方式二

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//实现动画的block_1
    //开始一个动画,block中写入实现动画
//    [UIView animateWithDuration:2 animations:^{
//        self.label.frame = CGRectMake(100, 100, 100, 100);
//    }];
    
    
//    //实现动画的block_2
//    [UIView animateWithDuration:2 animations:^{
//        self.label.frame = CGRectMake(100, 100, 100, 100);
//    }completion:^(BOOL finished) {
//            NSLog(@"%d=动画结束",finished);
//        
//     }];
    

//    //实现动画的block_3
//    [UIView animateWithDuration:2 delay:2 options:(UIViewAnimationOptionCurveEaseInOut) animations:^{
//        self.label.frame = CGRectMake(100, 100, 100, 100);
//    } completion:^(BOOL finished) {
//        NSLog(@"%d = 动画结束",finished);
//    }];
    
    
//    //实现动画的block_4
//    //Spring:模拟弹簧效果
//    //Damping:阻尼, 从0~1,值越小,动画越明显
//    //initialSpringVelocity:动画初始变化速率
//    [UIView animateWithDuration:2 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:150 options:(UIViewAnimationOptionCurveEaseInOut) animations:^{
//        self.label.center = CGPointMake(self.view.center.x, 100);
//    } completion:^(BOOL finished) {
//        NSLog(@"动画结束%d",finished);
//    }];

    
    //实现动画的block_5(关键帧动画)
    [UIView animateKeyframesWithDuration:3 delay:0 options:(UIViewKeyframeAnimationOptionRepeat) animations:^{
        //relativeDuration:设置为0.5,实际时间为0.5*3
        [UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.5 animations:^{
            self.label.center = self.view.center;
        }];
    } completion:^(BOOL finished) {
        NSLog(@"%d完成了",finished);
    }];
    
    
}

下边我们就来看下Layer动画

  • 1.核心动画的基本概念:
  • 1.1.coreAnimation核心动画,一组非常强大的动画处理API,可以用少量的代码,实现强大的功能.
  • 1.2.CoreAnimation可以用在Mac OS和iOS两个平台
  • 1.3.CoreAnimation动画的执行过程,都在后台操作,不会阻塞主线程
  • 1.4.CoreAnimation直接操作CALayer层,并不是UIView
  • 2.CAAnimation
  • 2.1.CAAnimation是所有动画对象的父类,负责控制动画的持续时间,和速度,它是一个抽象类,不能直接使用,应该使用它的子类
  • 2.2.属性说明:
    ①:duration:动画持续时间
    ②:repeatCount:动画的重复次数
    ③:repeatDuration:重复时间
    ④:removeOnCompletion(BOOL):默认为YES,表示动画执行完毕后就从图层上移除,图形会恢复到执行之前的状态.若想保持动画执行之后的状态,那就设置为NO,但是,还需要设置fillModel值为KCAFillModelForwards
    ⑤:fillMode:决定当前对象在非活动的时间段的行为,比如动画开始之前或者动画结束之后(想要fillMode有效,最好将removeOnCompletion=NO)
    • KCAFillModelRemove:默认值就是说当前动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
    • KCAFillModelForwards:当前动画结束后,layer会一直保存最后状态
    • KCAFillModeBackwards:在动画开始之前,只需将动画加入一个layer,layer便立即进入动画的初始状态并等待动画开始
    • KCAFillModelBoth:KCAFillModelForwards和KCAFillModeBackwards的合成

⑥:beginTime:可用来设置动画延迟时间,若想延迟两秒,则设置为CACurrentMediaTime()+2.其中的CACurrentMediaTime()为图层当前的时间
⑦timingFunction:速度控制函数,控制动画运行的节奏

  • CAMediaTimingFunctionLinear(线性):匀速.给你一个相对静态的感觉
  • CAMediaTimingFunctionEaseIn(淡入):动画缓慢进入,然后加速离开
  • CAMediaTimingFunctionEaseOut(淡出):动画全速进入,然后减速到达目的地
  • 2.3CAAnimation的子类:
- 2.3.1CABasicAnimation
- 2.3.2CAKeyFrameAnimation
- 2.3.3CAAnimationGroup
- 2.3.4CASpringAnimation
  • 2.4属性说明
    keypath:通过指定CALayer的一个属性名称为keypath(NSSting类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果,比如,指定@"position"为keypath,就相当于修改了CALayer的position属性的值,达到平移动画的效果
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

#pragma mark -----------------CABasicAnimation---------------
//1.创建
   //缩放动画
    CABasicAnimation *basic1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    basic1.fromValue = [NSNumber numberWithFloat:0.8f];
    basic1.toValue = [NSNumber numberWithFloat:2.0f];
    //旋转动画
    CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    basic.toValue = [NSNumber numberWithFloat:M_PI*4];
    //动画效果的初始值
    basic.fromValue = @50;
    //动画效果变换的结束值(绝对值)
    basic.toValue = @80;
//动画执行时间
    basic.duration = 4;
//    [_label.layer addAnimation:basic forKey:@"aaa"];

    #pragma mark -----------------CAKeyFrameAnimation---------------
    CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    CGPoint p1= CGPointMake(0, 0);
    CGPoint p2= CGPointMake(0, 400);
    CGPoint p3= CGPointMake(400, 100);
    CGPoint p4= CGPointMake(100, 200);
    CGPoint p5= CGPointMake(200, 300);
    NSValue *v1 = [NSValue valueWithCGPoint:p1];
    NSValue *v2 = [NSValue valueWithCGPoint:p2];
    NSValue *v3 = [NSValue valueWithCGPoint:p3];
    NSValue *v4 = [NSValue valueWithCGPoint:p4];
    NSValue *v5 = [NSValue valueWithCGPoint:p5];
    //values:NSArray对象,里面的元素称为"keyFrame(关键帧)",动画对象会在指定的时间里,依次显示values数组中的每一个关键帧
    keyframe.values = @[v1,v2,v3,v4,v5];
    keyframe.duration = 10;
    //可以设置每一帧的时间为比例的累加计算,取值范围0~1,若没设置,那么每一帧时间平分
    keyframe.keyTimes = @[@(0.1),@(0.2),@(1),@(1)];
    
    //将动画添加在layer层
//    [self.label.layer addAnimation:keyframe forKey:@"bbb"];
    

    
#pragma mark -----------------CAAnimationGroup---------------
    
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[basic1,basic,keyframe];
    group.duration = 10;
//    [self.label.layer addAnimation:group forKey:@"ccc"];
    
#pragma mark-------CASpringAnimation------
    
    CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"position.x"];
   //设置动画效果的初始值
    spring.fromValue = @150;
    //设置动画效果的结束值
    spring.toValue = @102;
    //阻尼系数
    spring.damping = 0;
    //刚度系数:(进度系数/弹性系数),系数越大,形变产生力越大,运动越快.
    spring.stiffness = 100;
    //质量:影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩幅度越大,动画运动波动大
    spring.mass = 50;
    //初始速率,速率为正,速度方向和运动方向一致,否则相反.
    spring.initialVelocity = -1;
    //结算时间,返回弹簧动画到停止时的估算时间,根据当前动画的各个参数估算,通常弹簧动画的时间使用结算时间比较准确
    spring.duration = spring.settlingDuration;

    [self.label.layer addAnimation:spring forKey:@"dddd"];
    
}

  • 3.关键帧动画与CABasicAnimation的区别
  • 3.1CABasicAnimation只能从一个数值(fromValue)变换到另一个数值(toValue)
  • 3.2关键帧动画,会使用一个NSArray保存这些数值
  • 4.动画组
  • 4.1属性说明:
    animation:用来保存一组动画对象的NSArray.
  • 4.1.2默认情况下,一组动画对象是同时运动的,也可通过设置动画的beginTime属性来更改动画开始时间

  • 5.转场动画
    CATransition:用于做转场动画效果,能够为layer层提供移除屏幕和移入屏幕的动画效果

    • 5.1动画属性
    • 5.1.1type:动画的过度效果
    • 5.1.2subtype:动画的过度方向
    • 5.1.3startProgress:动画起点(在整体动画的百分比)
    • 5.1.4endProgress:动画终点
- (void)viewDidLoad {
    [super viewDidLoad];
    _imageview = [[UIImageView alloc]init];
    _imageview.frame = [[UIScreen mainScreen]bounds];
    //图片在view上显示,且比例不变
    _imageview.contentMode = UIViewContentModeScaleAspectFit;
    self.imageview.image = [UIImage imageNamed: @"1.jpg"];
    [self.view addSubview:self.imageview];
    
    //添加手势
    UISwipeGestureRecognizer *left = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe)];
    [left setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    [self.view addGestureRecognizer:left];
    
    UISwipeGestureRecognizer *right = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe)];
        [right setDirection:(UISwipeGestureRecognizerDirectionRight)];
    [self.view addGestureRecognizer:right];
}


- (void)leftSwipe{
    [self transitionAnimation:YES];
}

- (void)rightSwipe{
    [self transitionAnimation:NO];

}

- (void)transitionAnimation:(BOOL)isNext{
//创建专场动画
    CATransition *tran = [[CATransition alloc]init];
    //效果
    tran.type = @"cube";
    //    // 动画的开始位置(0——1)
    //    tran.startProgress = 0;//默认为0
    //    // 动画的结束位置
    //    tran.endProgress = 1;//默认为1

    if (isNext) {
        tran.subtype = kCATransitionFromRight;
    }else{
        tran.subtype = kCATransitionFromLeft;
    }
    tran.duration = 1.0f;
    self.imageview.image = [self getImage:isNext];
    [self.imageview.layer addAnimation:tran forKey:@"Transition"];
}

- (UIImage *)getImage:(BOOL)isNext{
    if (isNext) {
        //eg:当currentIndex = 1时,(1+1)%5 = 2;
        self.currentIndex = (self.currentIndex +1)%IMAGE_COUNT;//IMAGE_COUNT宏定义照片总数
        
    }
    //前一张
    else{
        //eg:当currentIndex = 1时,(1-1+5)%5 = 0;
        self.currentIndex = (self.currentIndex -1+IMAGE_COUNT)%IMAGE_COUNT;
    }
    NSString *imageName = [NSString stringWithFormat:@"%ld.jpg",self.currentIndex +1];
    return [UIImage imageNamed:imageName];
}

CATransition的type效果表

类型字符串 效果说明
fade 交叉淡化过渡
push 新视图把旧视图推出去
moveIn 新视图移到旧视图上面
reveal 将旧视图移开,显示下面的新视图
cube 立方体翻转效果
oglFlip 上下左右翻转效果
suckEffect 收缩效果,像一块布被抽走
rippleEffect 水滴效果
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果
cameraIrisHollowOpen 相机镜头打开效果
cameraIrisHollowClose 相机镜头关闭效果

---------------------------------CALayer----------------------------
1.在iOS中,我们能看得见的,如按钮,文本,标签,输入框,等待,都是UIView
2.其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(CALayer对象),通过UIView的layer属性可以访问这个层
3.@property(nonatomic, strong)CALayer *layer;
4.当UIView需要显示在屏幕时,会调用drawRect:方法进行绘图,并且将所有绘制的内容在自己的图层上绘制,图层绘制完毕,系统将会拷贝图层到屏幕上,完成UIView的显示
5.UIView本身是布局有显示功能,真正拥有显示功能的是里面的layer层
6.通过UIView的图层,可以调整UIView的一些界面属性eg:圆角,边框,阴影

CALayer的坐标系统比UIView多了一个anchorPoint属性
anchorPoint锚点相对自身bounds来说,默认值为(0.5,0.5),即是anchorPoint的默认值在layer的中心点,它的值在0~1之间

QzAreq.png

- (void)viewlayer{
//设置阴影,透明度
    self.myview.layer.shadowOpacity = 1;
    //设置阴影色
    _myview.layer.shadowColor = [UIColor yellowColor].CGColor;
    //设置阴影圆角半径
    self.myview.layer.shadowRadius = 25;
    //设置圆角
    _myview.layer.cornerRadius = 100;
//    _myview.layer.masksToBounds = YES;
    //设置边框半径
    self.myview.layer.borderColor = [UIColor redColor].CGColor;
    //设置边框半径
    _myview.layer.borderWidth = 25;
    
}

- (void)Layer{
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    //设置位置
    layer.position = CGPointMake(200, 200);
//    layer.anchorPoint = CGPointMake(0, 0);
    layer.backgroundColor = [UIColor magentaColor].CGColor;
    [self.view.layer addSublayer:layer];

}

推荐阅读更多精彩内容