动画

一、Core Animation简介

(1)Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果
(2)Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
(3)Core Animation是直接作用在CALayer上的,并非UIView。

二、Core Animation的使用步骤

1.使用它需要先添加QuartzCore.framework框架和引人主头文件<QuartzCore/QuartzCore.h>
2.初始化一个CAAnimation对象,并设置一些动画相关属性
3.通过调用CALayer的addAnimation:forKey:方法增加CAAnimation对象到CALayer中,这样就能开始执行动画了
4.通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画

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

CATransition
(1)视图切换
(2)控制器切换

实例:
 //创建一个转场动画
    CATransition *transition = [CATransition animation];
    //设置动画时间
    transition.duration = 1;
    //动画类型
    /*
     CATransition中type的值:
     1     fade = 1,                   //淡入淡出
     2     push,                       //推挤
     3     reveal,                     //揭开
     4     moveIn,                     //覆盖
     5     cube,                       //立方体
     6     suckEffect,                 //吮吸
     7     oglFlip,                    //翻转
     8     rippleEffect,               //波纹
     9     pageCurl,                   //翻页
     10     pageUnCurl,                 //反翻页
     11     cameraIrisHollowOpen,       //开镜头
     12     cameraIrisHollowClose,      //关镜头
     */
    transition.type = @"pageCurl";

      //动画方向
    transition.subtype = kCATransitionFromLeft;

    //执行动画
    [self.imageView.layer addAnimation:transition forKey:nil];

2.关键帧动画

CAKeyframeAnimation

实例
//关键帧动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //动画时间
    animation.duration = 5;
    //设置关键点
    animation.values = @[
                         [NSValue valueWithCGPoint:CGPointMake(130, 130)],
                         [NSValue valueWithCGPoint:CGPointMake(300, 500)],
                         [NSValue valueWithCGPoint:CGPointMake(300, 40)],
                         [NSValue valueWithCGPoint:CGPointMake(30, 40)]
                         ];
    
    //设置运行的速率
    /*
     *  kCAMediaTimingFunctionLinear            线性,即匀速
                            *  kCAMediaTimingFunctionEaseIn            先慢后快
                            *  kCAMediaTimingFunctionEaseOut           先快后慢
                            *  kCAMediaTimingFunctionEaseInEaseOut     先慢后快再慢
                            *  kCAMediaTimingFunctionDefault           实际效果是动画中间比较快.
     */
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    //原路返回
    //animation.autoreverses = YES;
    
    //动画次数
    animation.repeatCount = 1;
    
    //停留在终点
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    //执行动画
    [redLayer addAnimation:animation forKey:nil];
构造路径、矩形、圆弧/圆心、线段、带有圆角的矩形、椭圆
//路径
    CGMutablePathRef path = CGPathCreateMutable();
#if 0
    //矩形
    CGPathAddRect(path, NULL, CGRectMake(30, 50, 300, 300));
    //圆弧,圆心(200,200) 半径100 开始弧度0  结束M_PI, true表示逆时针
    CGPathAddArc(path, NULL, 200, 200, 100, 0, M_PI, false);
     //线段
    CGPoint point[3] = {CGPointMake(30, 30),CGPointMake(300, 300),CGPointMake(300, 30),};
    CGPathAddLines(path, NULL, point, sizeof(point)/sizeof(point[0]));
    //带有圆角的矩形
    CGPathAddRoundedRect(path, NULL, CGRectMake(30, 50, 300, 300), 100, 100);
#endif
    
    //椭圆
    CGPathAddEllipseInRect(path, NULL, CGRectMake(30, 40, 300, 500));
    
    //构造贝塞尔曲线
   // CGPathAddCurveToPoint(<#CGMutablePathRef  _Nullable path#>, <#const CGAffineTransform * _Nullable m#>, <#CGFloat cp1x#>, <#CGFloat cp1y#>, <#CGFloat cp2x#>, <#CGFloat cp2y#>, <#CGFloat x#>, <#CGFloat y#>)
    
    
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //动画时间
    animation.duration = 3;
    //设置动画路径
    animation.path = path;
    //设置动画重复次数
    animation.repeatCount = MAXFLOAT;
    //执行动画
    [redLayer addAnimation:animation forKey:nil];
    
    //移除动画
    //[redLayer removeAnimationForKey:<#(nonnull NSString *)#>];
    
    CGPathRelease(path);

(1)values
(2)path(加入购物车)
(3)输入框输入错误动画

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];
    animation.duration = 0.15;
    //关键点
    animation.values = @[@(10),@(0),@(-10),@(0)];
    
    //相对于当前的坐标为参考,也就是在当前的位置基础上移动了多少
    animation.additive = YES;
    //动画次数
    animation.repeatCount = 2;
    [self.textField.layer addAnimation:animation forKey:nil];
    
}

(4)视图抖动效果(系统桌面图标删除效果)

//角度转化为弧度
#define kToDian(angle) (M_PI/180 * (angle))
//长按
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPress
{
    if (longPress.state == UIGestureRecognizerStateBegan)
    {
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
        animation.values = @[@(kToDian(5)),@(kToDian(0)),@(kToDian(-5)),@(kToDian(0))];
        animation.duration = 0.2;
        animation.repeatCount = MAXFLOAT;
        //执行动画
        [longPress.view.layer addAnimation:animation forKey:@"animaiton"];
        
        //3秒停止动画
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            //停止动画 - 移除指定动画
            [longPress.view.layer removeAnimationForKey:@"animaiton"];
            //移除所有动画
            //[longPress.view.layer removeAllAnimations];
        });
    }
}

(5)点赞动画

calculationMode 是控制关键帧动画时间的另一种方法。我们通过将其设置为 kCAAnimationPaced,让 Core Animation 向被驱动的对象施加一个恒定速度,不管路径的各个线段有多长。

additive 属性为 YES 能够对所有形式的需要更新的元素重用相同的动画,且无需提前知道它们的位置。

3.隐式动画

CABasicAnimation
(1)旋转

//隐式动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.duration = 1;
    //结束的位置
    animation.toValue = @(M_PI * 2);
    //
    animation.repeatCount = MAXFLOAT;
    [imageView.layer addAnimation:animation forKey:nil];

(2)摇一摇(微信摇一摇)

//启动摇一摇
    [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;

/**
 *  摇一摇开始会触发
 *
 *  @param motion <#motion description#>
 *  @param event  <#event description#>
 */
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"shake_sound_male.wav" ofType:nil];
    
    //1.播放音频
    _player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
    //播放音频
    [_player play];
    
    //2.动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
    animation.duration = 0.5;
    //原路返回
    animation.autoreverses = YES;
    //向上移动25
    animation.toValue = @(-25);
    [self.topImageView.layer addAnimation:animation forKey:nil];
    
    //下面的图片向下移动 25
    animation.toValue = @(25);
    [self.bottomImageView.layer addAnimation:animation forKey:nil];
    
    
    //TODO::请求数据
}
byValue和toValue的区别,前者是在当前的位置上增加多少,后者是到指定的位置。

4.CAAnimationGroup 动画组

变色变形效果例子

 /*
     1.背景颜色动画
     */
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    //动画时间
    animation.duration = 3;
    //动画起始状态
    animation.fromValue = (__bridge id _Nullable)([UIColor redColor].CGColor);
    //动画终点状态
    animation.toValue = (__bridge id _Nullable)([UIColor greenColor].CGColor);
    animation.autoreverses = YES;
    animation.repeatCount = MAXFLOAT;
    //执行动画
    [layer addAnimation:animation forKey:nil];
    
    /*
     2.圆角半径动画
     */
    CABasicAnimation *cornerRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
    //动画时间
    cornerRadiusAnimation.duration = 3;
    //动画起始状态
    cornerRadiusAnimation.fromValue = @(0);
    //动画终点状态
    cornerRadiusAnimation.toValue = @(100);
    cornerRadiusAnimation.autoreverses = YES;
    cornerRadiusAnimation.repeatCount = MAXFLOAT;
    //执行动画
    [layer addAnimation:cornerRadiusAnimation forKey:nil];

仿真动画

/**
 *  重力行为
 */
@property (nonatomic, strong) UIGravityBehavior *gravity;

/**
 *  碰撞行为
 */
@property (nonatomic, strong) UICollisionBehavior *collision;

/**
 *  仿真行为的执行者
 */
@property (nonatomic, strong) UIDynamicAnimator *animator;
/**
 *  仿真行为的执行者
 */
- (UIDynamicAnimator *)animator
{
    if (!_animator)
    {
        _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    }
    
    return _animator;
}

/**
 *  重力行为
 *
 *  @return <#return value description#>
 */
- (UIGravityBehavior *)gravity
{
    if (!_gravity)
    {
        _gravity = [[UIGravityBehavior alloc] init];
    }
    
    return _gravity;
}

/**
 *  碰撞行为
 */
- (UICollisionBehavior *)collision
{
    if (!_collision)
    {
        _collision = [[UICollisionBehavior alloc] init];
        //设置边沿
        _collision.translatesReferenceBoundsIntoBoundary = YES;
    }
    
    return _collision;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
   
    
    
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(createItem) userInfo:nil repeats:YES];
    
}

/**
 *  创建仿真对象,并在添加重力和碰撞行为,然后执行
 */
- (void)createItem
{
    /*
     仿真行为:
     1、要有仿真元素。一般是UIView。
     2.仿真行为。
     3.仿真行为执行者。
     */
    
    //仿真元素
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(arc4random_uniform(self.view.frame.size.width) - 40, 40, 40, 40)];
    view.backgroundColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0];
    [self.view addSubview:view];
    
    
    //添加重力行为
    [self.gravity addItem:view];
    //添加碰撞行为
    [self.collision addItem:view];
    
    //执行重力行为
    [self.animator addBehavior:self.gravity];
    //执行碰撞行为
    [self.animator addBehavior:self.collision];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容