Core Animation

一、Core Animation简介

(1)Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果 

(2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。 

(3)Core Animation是直接作用在CALayer上的,并非UIView。

(4)什么是Core Animation?

 

 CAAnimation可分为四种:

  • CABasicAnimation

    通过设定始末两点和动画时间,动画会沿着这两点进行移动。可以看做只有始末两点的特殊的CAKeyFrameAnimation。

  • CAKeyframeAnimation

    Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame 和 动画的时间,动画会沿你设定的轨迹进行移动。

  • CAAnimationGroup

    Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时按顺序执行。

  • CATransition

    这个就是苹果帮开发者封装好的一些动画。

 

 

二、Core Animation的使用步骤 

 

1.使用它需要先添加QuartzCore.framework框架和引入主头文件<QuartzCore/QuartzCore.h> 

2.初始化一个CAAnimation对象,并设置一些动画相关属性 

3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了 

4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

 

 

三、CAAnimation 的属性(多数动画的公共属性)

 

CoreAnimation - CAAnimation.h 中:

  • timingFunction

    定义动画的运动节奏,默认值是0(线性的)。比如是均匀变化(相同时间变化量相同)还是先快后慢,先慢后快还是先慢再快再慢。   

    动画的开始与结束的快慢,有五个预置分别为(下同):

      *  kCAMediaTimingFunctionLinear            线性,即匀速

      *  kCAMediaTimingFunctionEaseIn            先慢后快

         *  kCAMediaTimingFunctionEaseOut           先快后慢

         *  kCAMediaTimingFunctionEaseInEaseOut     先慢后快再慢

         *  kCAMediaTimingFunctionDefault           实际效果是动画中间比较快.

 

  • removedOnCompletion

     BOOL值,默认YES。指当动画结束时,是否从渲染树移除动画。由这个属性可以看出,动画效果其实就是一个假象一个效果,动画并不会改变对象的frame。

 

CoreAnimation - CAMediaTiming.h 中: 

  • repeatCount

    float,动画重复的次数。 

 

  • autoreverses

    BOOL值,默认NO。当动画结束时,是否倒着重复一遍动画。

 

  • fillMode

    定义对象在活动时间以外的行为(动画结束后的行为),可以强制让对象的行为(动画)停留在活动结束时的某一刻(前、后、中间)或者移除对象的行为(动画)。

    强制设置对象的行为: 

     * NSString * const kCAFillModeForwards  结束前

    * NSString * const kCAFillModeBackwards   结束后

    * NSString * const kCAFillModeBoth    中间

    * NSString * const kCAFillModeRemoved  移除行为

注意:如果想要规定动画停止时的行为,必须同时设置一下两属性:

    removedOnCompletion  和  fillMode

 

@interface CAPropertyAnimation : CAAnimation

  --->  CABasicAnimation  和  CAKeyframeAnimation  公有的属性

 

  • additive

    默认NO。当置YES时,新设置的animation.values的值将被『附加』到目前描述Layer的属性的值上,以产生新的描述值。(而不是取代当前值)

    e.g.输入框输入错误动画--下面关键帧动画的实例。

 

 

 

三、动画类型 

 

1.CATransition过渡动画(转场动画)  

  • CATransitionCAAnimation的子类,实际上是苹果帮开发者封装好的一些动画,专门用于做转场动画。(能够为层和视图控制器提供移出屏幕和移入屏幕的动画效果)
  • 设置转场动画的过程

    a.创建转场动画: [CATransition animation]

    b.设置动画属性值

    c.添加到需要转场动画的图层上  [layer addAnimation:animation forKey:nil]

  • CATransition动画属性:  

    • type动画过渡类型    

type的值:转场动画的类型(NSString *type)

动画类型说明对应常量是否支持方向设置
公开API   
fade 淡出效果 kCATransitionFade
movein 新视图移动到旧视图上 kCATransitionMoveIn
push 新视图推出旧视图 kCATransitionPush
reveal 移开旧视图显示新视图 kCATransitionReveal
私有API  ----  私有API只能通过字符串访问,如@"cube" 
cube 立方体翻转效果
oglFlip 翻转效果
suckEffect 收缩效果
rippleEffect 水滴波纹效果
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果
cameralIrisHollowOpen 摄像头打开效果
cameraIrisHollowClose 摄像头关闭效果


  下面这个几个用在UIView的setAnimationTransition方法中
  13     UIViewAnimationTransitionCurlDown,   //下翻页
  14     UIViewAnimationTransitionCurlUp,       //上翻页
  15     UIViewAnimationTransitionFlipFromLeft,   //左翻转
  16     UIViewAnimationTransitionFlipFromRight, //右翻转

    • subtype:动画过渡方向

subtype的值转场动画的方向(NSString *subtype)

  从某个方向开始:fromLeftfromRightfromTop ,fromBottom

  也可以通过输入上方的字符串来调用这些方法。

动画子类型说明
kCATransitionFromRight 从右侧转场
kCATransitionFromLeft 从左侧转场
kCATransitionFromTop 从顶部转场
kCATransitionFromBottom 从底部转场

 

    • startProgress:动画起点(在整体动画的百分比),默认值为0.0。必须小于等于结束点。

    • endProgress:动画终点(在整体动画的百分比),默认值为1.0。必须大于等于开始点。

CATransition中endProgress:转场动画的终点(完整动画的百分之几)(float endProgress)

  想要动画成功地停止在设置的点,需要同时设置动画的以下几个属性

  • animation.endProgress = 0.7;
  • animation.fillmode = CAFillModeForwards  kCAFillModeBoth;  //设置活动时间外的行为
  • animation.removedOnCompletion = NO;    //在动画执行完成时,是否被移除(默认是)
    • filter:动画的滤镜(可选的)

 

CATransition中的filter:转场动画的滤镜(CIFiler *filter)

  如果指定,那么指定的filter必须同时支持x和y,否则该filter将不起作用。默认值为nil。

  如果设置了filter,那么,为layer设置的type和subtype属性将被忽略。

  该属性只在iOS 5.0以及以后版本被支持。

 

  • CATransition转场动画的实际应用: 

  (1)视图切换

  应用:用酷炫的动画效果实现单个UIImageView上切换不同图片

     

 

#import "ViewController.h"

@interface ViewController ()
{
    NSInteger _count;
}

@property (nonatomic, weak) UIImageView *imageView;

@end

@implementation ViewController

- (UIImageView *)imageView
{
    if (!_imageView)
    {
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"%ld",_count]]];
        imageView.frame = CGRectMake(20, 70, self.view.frame.size.width - 40, self.view.frame.size.width - 40);
        imageView.userInteractionEnabled = YES;
        [self.view addSubview:imageView];
        
        _imageView = imageView;
    }
    
    return _imageView;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    _count = 1;
    
    UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
    //设置轻扫方向
    leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.imageView addGestureRecognizer:leftSwipe];
    
    UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
    rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
    [self.imageView addGestureRecognizer:rightSwipe];
}

//处理轻扫手势
- (void)swipeGesture:(UISwipeGestureRecognizer *)swipe
{
    //转场动画
    CATransition *animation = [CATransition animation];
    //动画时间
    animation.duration = 1.0f;
    //display mode, slow at beginning and end
    animation.timingFunction = UIViewAnimationCurveEaseInOut;
    //在动画执行完时是否被移除
    animation.removedOnCompletion = NO;
    //过渡效果
    animation.type = @"pageCurl";
    //过渡方向
    animation.subtype = kCATransitionFromRight;
    //暂时不知,感觉与Progress一起用的,如果不加,Progress好像没有效果
    animation.fillMode = kCAFillModeForwards;
    //动画停止(在整体动画的百分比).
    animation.endProgress = 0.7;
    
    animation.startProgress = 0.5;
    if (swipe.direction == UISwipeGestureRecognizerDirectionLeft)
    {
        NSLog(@"向左");
        
        _count++;
        
        //方向
        animation.subtype = kCATransitionFromRight;
    }
    else if(swipe.direction == UISwipeGestureRecognizerDirectionRight)
    {
        NSLog(@"向右");
        
        _count--;
        
        //方向
        animation.subtype = kCATransitionFromLeft;
    }
    else if (swipe.direction == UISwipeGestureRecognizerDirectionUp)
    {
        NSLog(@"向上");
    }
    else
    {
        NSLog(@"向下");
    }
    
    //添加动画
    [self.imageView.layer addAnimation:animation forKey:nil];
    
    //重新修改图片
    self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",_count]];
}

 

  

  (2)控制器切换

 

2.CAKeyframeAnimation 关键帧动画

  • 提供 「CALayer的始点、中间关键点、终点的位置」 或者 「一条路径」,动画会沿你设定的轨迹进行移动。

 

  • 创建CAKeyframeAnimation需要用到『KeyPath』
    • e.g. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];

  支持CAKeyframeAnimation的keyPath:

  

   注意:上面表格里面的key前面都需要加上transform

  • 属性解析
    • values:是一个NSArray对象。里面的元素称为『关键帧』(keyframe)。动画对象会在指定的时间(duration)内,依次移动到values数组中的每一个关键帧。

    •  path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。values和path是互斥的:如果你设置了path,那么values将被忽略。

    • keyTimes该属性是一个数组,可以为每个关键帧(子路径AB,BC,CD)指定对应的时间点。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7。当keyTimes没有设置的时候,各个关键帧的时间是平分的。

    • timeFunctions:上方已提出,简单地说就是设置动画的快慢。

需要注意的是:若keyTimes未设置(各帧时间平分),timesFunctions选择匀速,此时意味着每一段动画都是匀速,而非意味着每一段动画的速度都是相同的。因为速度还取决与距离:时间相同、确定是匀速运动,但是距离不同,所以匀速但速度不同!

    • calculationMode:用来设定每两个关键帧中间的行为(包括重复第二次播放时,上次结尾和下次开头中间的转换是否连续),决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似。

 calculationMode的值

const   kCAAnimationLinear    //线性,默认
const   kCAAnimationDiscrete   //离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上 const   kCAAnimationPaced    //平均,keyTimes跟timeFunctions失效 const   kCAAnimationCubic    //平均,同上 const   kCAAnimationCubicPaced  //平均,同上

 

  • 应用实例

(1)values:关键位置数组(设定几个关键点)

 

    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.position = self.view.center;
    [self.view.layer addSublayer:layer];
    
    //关键帧动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];
    //动画时间
    animation.duration = 5;
    //动画的关键部分
    animation.values = @[@(10),@(30),@(80),@(300)];
    
#if 0
    //关键帧动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //动画时间
    animation.duration = 5;
    //动画的关键部分
    animation.values = @[[NSValue valueWithCGPoint:CGPointMake(10, 10)],
                         [NSValue valueWithCGPoint:CGPointMake(200, 200)],
                          [NSValue valueWithCGPoint:CGPointMake(200, 400)],
                           [NSValue valueWithCGPoint:CGPointMake(10, 10)]];
#endif
    //动画的节奏
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    //原路返回
    animation.autoreverses = YES;
    //停留在动画结束的位置
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    //添加动画并且执行
    [layer addAnimation:animation forKey:nil];

  

(2)path:关键路径(通过CGPath设定一条自定义的路线)

 

    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer];
    
    //创建动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //动画时间
    animation.duration = 5;
    //设置动画次数
    animation.repeatCount = MAXFLOAT;
    //恒定的速度运动
    animation.calculationMode = kCAAnimationPaced;
    
    //创建一个路径
    CGMutablePathRef path = CGPathCreateMutable();
#if 0
    //椭圆
    CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 400));
#endif
    //矩形
    CGPathAddRect(path, NULL, CGRectMake(100, 100, 200, 400));
    
    //设置动画的路径
    animation.path = path;
    //释放path
    CGPathRelease(path);
    
    //执行动画
    [layer addAnimation:animation forKey:@"key"];
    //5秒移除动画
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [layer removeAnimationForKey:@"key"];
    });

 

 

注意记得释放path

 

 

(3)加入购物车:用贝塞尔曲线,画一条『path』抛物线(CGMutablePathRef),让动画沿着抛物线走

  关键点:坐标转换 + 贝尔塞曲线的绘制(起点、终点、控制点『前两点切线交点』) + 核心动画

  • CGPoint point = [self convertPoint:sender.center toView:self.superview];
  • CGPoint startPoint = [self.tableView convertPoint:point toView:self.view];

 

  • CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);

 

Cell :

#import <UIKit/UIKit.h>

typedef void(^CarButtonClick)(CGPoint point);

@interface Cell : UITableViewCell

- (void)setCarButtonClick:(CarButtonClick)hanlde;

@end

#import "Cell.h"

@interface Cell ()
{
    CarButtonClick _carButtonClick;
}

- (IBAction)buttonClick:(UIButton *)sender;

@end

@implementation Cell

- (void)awakeFromNib {
    self.selectionStyle = UITableViewCellSelectionStyleNone;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
}

- (void)setCarButtonClick:(CarButtonClick)hanlde
{
    _carButtonClick = hanlde;
}

- (IBAction)buttonClick:(UIButton *)sender
{
#pragma mark 坐标转换第一步
    //按钮中心点转化为tableView的坐标系,返回一个新的坐标点
    CGPoint point = [self convertPoint:sender.center toView:self.superview];
    NSLog(@"%@",NSStringFromCGPoint(point));
    
    //回调
    if (_carButtonClick)
    {
        _carButtonClick(point);
    }
}
@end

 

 ViewController 中 tableView的关键设置

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    Cell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    
    [cell setCarButtonClick:^(CGPoint point)
     {
         //起点
         #pragma mark 坐标转换第二步
         //把point转化为self.view的坐标系
         CGPoint startPoint = [self.tableView convertPoint:point toView:self.view];
         //NSLog(@"%@",NSStringFromCGPoint(startPoint));
         
         //终点
         CGPoint endPoint = _carCenter;
         
         //控制点(起点和终点切线交点)
         CGPoint controlPoint = CGPointMake(endPoint.x, startPoint.y);
         
         //创建一个物体
         CALayer *layer = [CALayer layer];
         layer.frame = CGRectMake(0, 0, 30, 30);
         layer.position = startPoint;
         layer.backgroundColor = [UIColor redColor].CGColor;
         layer.cornerRadius = 15;
         [self.view.layer addSublayer:layer];
         
         CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
         animation.duration = 3;
         //坐标停留在终点
         animation.removedOnCompletion = NO;
         animation.fillMode = kCAFillModeForwards;
         //设置代理
         animation.delegate = self;
         
         //创建一个二次贝塞尔曲线
         CGMutablePathRef path = CGPathCreateMutable();
         //设置起点
         CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
         //(cpx,cpy)表示控制点  (x,y)终点
         CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);
         
         //设置曲线路径
         animation.path = path;
         //执行动画
         [layer addAnimation:animation forKey:nil];
         //释放
         CGPathRelease(path);
    }];
    return cell;
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    NSLog(@"动画完成");
}

 

 

(4)输入框输入错误动画:设置简单的『values』,使其来回抖动

  • animation.additive = YES;
#import "ViewController.h"
@interface ViewController ()
{
    UITextField *_textField;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _textField = [[UITextField alloc] initWithFrame:CGRectMake(90, 80, 200, 40)];
    _textField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:_textField];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];
    animation.duration = 0.2;
    animation.values = @[@(-5),@(0),@(5),@(0),@(-5)];

    //additive 属性为 YES 能够在原属性值的基础上,附加values设置的值上去,产生新的描述结果。
    animation.additive = YES;
    
//    animation.repeatCount = 2;
    [_textField.layer addAnimation:animation forKey:nil];
}
@end

 

(5)视图抖动效果:角度转换为弧度,在Z轴上添加旋转。

移动改x或y轴,旋转改z轴。

 

  • animation.values = @[@(kToRadian(-5)), @(kToRadian(0)), @(kToRadian(5)), @(kToRadian(0)), @(kToRadian(-5))];  //弧度

 

#import "ViewController.h"
//角度转化为弧度
#define kToRadian(r) (M_PI/180*(r))
//返回两个值的最小值
#define kMin(a,b) ((a)>(b)?(b):(a))
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(90, 90, 100, 100)];
    v.backgroundColor = [UIColor redColor];
    v.layer.cornerRadius = 10;
    [self.view addSubview:v];
    
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressHandle:)];
    [v addGestureRecognizer:longPress];
}

- (void)longPressHandle:(UILongPressGestureRecognizer *)longPress
{
 
    //长按开始执行动画
    if (longPress.state == UIGestureRecognizerStateBegan)
    {
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
        //动画时间
        animation.duration = 0.2;
        //动画次数
        animation.repeatCount = MAXFLOAT;
        //弧度
        animation.values = @[@(kToRadian(-5)),
                             @(kToRadian(0)),
                             @(kToRadian(5)),
                             @(kToRadian(0)),
                             @(kToRadian(-5))];
        
        [longPress.view.layer addAnimation:animation forKey:@"key"];
        
        //五秒后移除动画
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [longPress.view.layer removeAnimationForKey:@"key"];
        });
    }
}

 

 

(6)点赞动画

 

- (IBAction)buttonClick:(UIButton *)sender
{
    sender.selected = !sender.selected;
    
    //比例变化
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
    animation.duration = 0.5;
    
    //👍
    if (sender.selected)
    {
        //比例变化
        animation.values = @[@(1.2),@(2),@(1)];
    }
    //取消👍
    else
    {
        //比例变化
        animation.values = @[@(0.8),@(0.2),@(1)];
    }

    //执行动画
    [sender.layer addAnimation:animation forKey:nil];
}

 

3.CABasicAnimation基本动画(隐式动画) 

  • 属性分析:三个属性都是可选的,且至少一个不为nil。动画加点不为nil的两点之间。
    • 三个属性:fromValue(起点)、toValue(终点)、byValue(附加值)

    • 六种情况:

* - both `fromValue' and `toValue' non-nil. Interpolates between `fromValue' and `toValue'.

* - `fromValue' and `byValue' non-nil. Interpolates between `fromValue' and `fromValue' plus `byValue'.

* - `byValue' and `toValue' non-nil. Interpolates between `toValue' minus `byValue' and `toValue'.

* - `fromValue' non-nil. Interpolates between `fromValue' and the current presentation value of the property.

* - `toValue' non-nil. Interpolates between the layer's current value of the property in the render tree and `toValue'.

* - `byValue' non-nil. Interpolates between the layer's current value of the property in the render tree and that plus `byValue'.

 

 

  • 支持CABasicAnimation的keyPath:

包括支持CAKeyframeAnimation的keyPath

 

以及:

  opacity = 透明度

    margin

    zPosition

    backgroundColor    背景颜色

    cornerRadius    圆角

    borderWidth

    bounds

    contents

    contentsRect

    hidden

    mask

    masksToBounds

    opacity

    position

    shadowColor

    shadowOffset

    shadowOpacity

    shadowRadius

 

  • 应用实例:

(1)旋转

 

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sync"]];
    imageView.frame = CGRectMake(0, 0, 100, 100);
    imageView.center = self.view.center;
    [self.view addSubview:imageView];
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    //设置动画时间
    animation.duration = 1;
    //起点
    animation.fromValue = @(0);
    //终点
    animation.toValue = @(2*M_PI);
    //重复次数,一直重复
    animation.repeatCount = MAXFLOAT;
    //添加动画
    [imageView.layer addAnimation:animation forKey:nil];
    //当图片加载完后,直接移除动画

 

(2)摇一摇

  • [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES; //摇动手势

 

 

- (void)viewDidLoad {
    [super viewDidLoad];
    //启动摇一摇
    [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
}

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    NSLog(@"摇一摇开始");
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
    animation.duration = 0.5;
    
    //原路返回,这样就只用设置去程
    animation.autoreverses = YES;

    //translation相对原来的位移偏移量
    animation.toValue = @(-50);
    [self.topImageView.layer addAnimation:animation forKey:nil];
    
    animation.toValue = @(50);
    [self.bottomImageView.layer addAnimation:animation forKey:nil];
}

 

(3)其他:背景色和圆角

    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(0, 0, 100, 100);
    layer.position = self.view.center;
    layer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer];
    

    //背景颜色的动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    animation.duration = 3;
    //这里强制转换
    animation.toValue = (id)[UIColor greenColor].CGColor;
    
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.autoreverses = YES;
    animation.repeatCount = MAXFLOAT;
    
    
    [layer addAnimation:animation forKey:nil];
    
    
    //圆角半径
    animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
    animation.duration = 3;
    animation.toValue = @(50);
    animation.autoreverses = YES;
    animation.repeatCount = MAXFLOAT;
    
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    
    [layer addAnimation:animation forKey:nil];

 

4.CAAnimationGroup动画组

  • 用于把类似的动画放在一组,方便管理。比如上面这个例子,就可以用动画组来创建。
    CALayer *layer = [CALayer layer];
    layer.frame = CGRectMake(0, 0, 100, 100);
    layer.position = self.view.center;
    layer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:layer];
    

    //背景颜色的动画
    CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    animation1.toValue = (id)[UIColor greenColor].CGColor;
    

    //圆角半径
    CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
    animation2.toValue = @(50);
   

    CAAnimationGroup *group = [CAAnimationGroup animation];
    //管理动画,数组的里面的动画是同时执行
    group.animations = @[animation1,animation2];
    group.duration = 3;
    group.removedOnCompletion = NO;
    group.fillMode = kCAFillModeForwards;
    group.autoreverses = YES;
    group.repeatCount = MAXFLOAT;
    
    //执行
    [layer addAnimation:group forKey:nil];

 

posted on 2016-03-26 00:48  Wilson_CYS  阅读(437)  评论(0编辑  收藏  举报

导航