iOS CoreAnimation详解(一) 有关Layer的动画

以前由于项目需要 也写了一些动画 ,但是知识不系统,很散。这段时间趁着项目完成的空袭,来跟着大神的脚步系统的总结一下iOS中Core Animation的知识点。

原博客地址:http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html

本文主要从CoreAnimation的Layer角度来讲解动画,我想从CALayer的角度更好理解,后续还会有第二篇从UIKIt的UIView角度来讲解动画,第三篇讲解UIDynamicAnimation,第三篇我会讲到UIViewController切换时候的动画。

本文主要涵盖四个部分

1.基础动画 会讲到时间函数和一些关键的属性

2.基于关键帧的动画 讲到沿着指定路径运行的动画

3.动画组 多个动画组合到一起形成复杂的动画

4.简单讲一讲有关动画的代理

一 为什么要设计动画

动画提供了一个渐变的方式来表达变化,使用动画可以避免各种动画突变,造成用户困惑。

iOS中,使用CoreAnimation只要指定始末状态或者关键帧状态,CoreAnimation会高效的为我们创建补间动画。

二 从CALayer的角度来看三种动画

首先不熟悉CALayer的同学看看前两篇的CALayer的内容,这是CoreAnimation的基础。这里我重复的介绍两种CALayer的Tree。
Presentation Tree-对应在动画的过程中,CALayer的属性
Model Tree-对应CALayer的实际属性。
通过使用 -[CALayer presentationLayer] 和 -[CALayer modelLayer]可以访问两种Tree
动画的过程实际上是修改Presentation Tree

2.1 基础的动画

第一个简单的动画,我希望imageview向右移动100的距离,移动方式easeInOut(加速开始,减速结束)。

代码如下,通常有两种方式来影响动画

CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"position.x";//KVC的方式来访问属性
    animation.fromValue = @(self.imageView.layer.position.x);//该属性开始的值
    animation.toValue = @(self.imageView.layer.position.x + 100);//该属性的结束值
    animation.duration = 1;//完成一次动画需要的时间
    //设置动画进行的方式
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [self.imageView.layer addAnimation:animation forKey:@"basic"];

通过fromValue和toValue是一种方式,当然也可以通过byValue的方式,byValue在初值上加上byValue的变化,通过以下代码也可以实现上述动画

    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"position.x";//KVC的方式来访问属性
//    animation.fromValue = @(self.imageView.layer.position.x);//该属性开始的值
//    animation.toValue = @(self.imageView.layer.position.x + 100);//该属性的结束值
    animation.byValue = @(100);
    animation.duration = 1;//完成一次动画需要的时间
    //设置动画进行的方式
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [self.imageView.layer addAnimation:animation forKey:@"basic"];

但是,结束后会发现,imageview又恢复到原处。这是因为在动画的过程中,我们修改的是Presentation Tree,并没有实际修改CALayer的属性。想要让动画停在结束的位置,通常有两种方式,

(1)修改属性
代码如下

CABasicAnimation * animation = [CABasicAnimation animation];
  animation.keyPath = @"position.x";
  animation.fromValue = @(self.imageview.layer.position.x);
  animation.toValue = @(self.imageview.layer.position.x + 100);
  animation.duration = 1;
  animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  [self.imageview.layer addAnimation:animation forKey:@"basic"];
  self.imageview.layer.position = CGPointMake(self.imageview.layer.position.x+100, self.imageview.layer.position.y);  

(2)设置让动画停在结束的位置

CABasicAnimation * animation = [CABasicAnimation animation];
    animation.keyPath = @"position.x";
    animation.fromValue = @(self.imageview.layer.position.x);
    animation.toValue = @(self.imageview.layer.position.x + 100);
    animation.duration = 1;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.removedOnCompletion = NO;//动画结束了禁止删除
    animation.fillMode = kCAFillModeForwards;//停在动画结束处
    [self.imageview.layer addAnimation:animation forKey:@"basic"];  

一般采用前者,因为动画往往的结束是实际的属性的改变。

这里再讲解下时间函数
时间函数决定了动画如何执行,时间函数决定了动画的数学模型,比如速度速度最好不要有突变, 系统提供的时间函数有以下几种

NSString *constkCAMediaTimingFunctionLinear;线性
NSString *constkCAMediaTimingFunctionEaseIn;加速进入
NSString *constkCAMediaTimingFunctionEaseOut;减速停止
NSString*constkCAMediaTimingFunctionEaseInEaseOut;加速进入减速停止,这个是常用的
NSString *constkCAMediaTimingFunctionDefault;默认
当然,时间函数支持自定义,用如下函数
functionWithControlPoints::::
这个函数的4个点决定了一个三维的贝塞尔曲线来决定时间函数。这里不深入讲解了。
最后,这一点尤为重要,就是在传递CAAnimation的对象或者子类给Layer的时候,传递的是copy

2.2 基于关键帧的动画
以下是一个基于关键帧创建的抖动的动画,采用在时间点对应的位置来创建动画

CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position.x";
    NSInteger initalPositionX = self.imageView.layer.position.x;
    animation.values = @[@(initalPositionX),
                         @(initalPositionX + 10),
                         @(initalPositionX - 10),
                         @(initalPositionX + 10),
                         @(initalPositionX)];
    animation.keyTimes = @[
                           @(0),
                           @(1/6.0),
                           @(3/6.0),
                           @(5/6.0),
                           @(1)];
    [self.imageView.layer addAnimation:animation forKey:@"keyFrame"];

当然,基于关键帧的动画支持沿着路径运动,可以设置时间函数来决定运动的方式
例如以下创建一个比较复杂的运动,首先移动到(200,200),然后沿着以该点为圆心,逆时针旋转半圈,最后停在结束的位置。
动画的过程中,imageview沿着路径转动

CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    //Create Path
    CGMutablePathRef mutablepath = CGPathCreateMutable();
    CGPathMoveToPoint(mutablepath, nil,self.imageView.layer.position.x, self.imageView.layer.position.y);
    CGPathAddLineToPoint(mutablepath,nil,200,200);
    CGPathAddArc(mutablepath, nil,200,200,100,0,M_PI,YES);
    //set path
    animation.path = mutablepath;
    animation.duration = 4.0;
    animation.rotationMode = kCAAnimationRotateAuto;
    animation.removedOnCompletion = NO;//动画结束了禁止删除
    animation.fillMode = kCAFillModeForwards;//停在动画结束处
    [self.imageView.layer addAnimation:animation forKey:@"PathAnimation"];

2.3 动画组
所谓,动画组就是把几个动画组合到一起,然后一起执行,通常复杂的动画都是由动画组来实现的。
举个例子:沿着上个例子的路径运动,运动的同时透明度渐变。

CAKeyframeAnimation * pathAnimation = [CAKeyframeAnimation animation];
  pathAnimation.keyPath = @"position";
  //Create Path
  CGMutablePathRef mutablepath = CGPathCreateMutable();
  CGPathMoveToPoint(mutablepath, nil,self.imageview.layer.position.x, self.imageview.layer.position.y);
  CGPathAddLineToPoint(mutablepath,nil,200,200);
  CGPathAddArc(mutablepath, nil,200,200,100,0,M_PI,YES);
  //set path
  pathAnimation.path = mutablepath;
  pathAnimation.rotationMode = kCAAnimationRotateAuto;
  [self.imageview.layer addAnimation:pathAnimation forKey:@"PathAnimation"];  

  //透明度变化
  CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animation];
  opacityAnimation.keyPath = @"opacity";
  opacityAnimation.values = @[@(1.0),
                       @(0.5),
                       @(0.0),
                       @(0.5),
                       @(1.0)];
  opacityAnimation.calculationMode = kCAAnimationPaced;
  [self.imageview.layer addAnimation:opacityAnimation forKey:@"OpacityAnination"];
  //配置动画组
  CAAnimationGroup * animationGroup = [[CAAnimationGroup alloc] init];
  animationGroup.animations = @[pathAnimation,opacityAnimation];
  animationGroup.duration = 4.0;
  animationGroup.removedOnCompletion = NO;
  animationGroup.fillMode = kCAFillModeBackwards;
  [self.imageview.layer addAnimation:animationGroup forKey:@"GroupAnimation"];  

(三)动画的代理
通过设置代理可以监听动画开始和结束的事件
通过设置delegate,来监听两个函数
animationDidStart:(CAAnimation *)anim
animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
这里的flag判断动画是否执行完毕

时间: 2024-12-30 21:34:47

iOS CoreAnimation详解(一) 有关Layer的动画的相关文章

iOS Animation详解

iOS Animation详解 本篇只要讲解iOS中动画的使用. Animtion主要分为两类:UIView动画和CoreAnimation动画. UIView动画有UIView属性动画,UIViewBlock动画,UIViewTransition动画. 而CoreAnimation动画主要通过CAAnimation和CALayer,常用的有CABasicAnimation,CAKeyframeAnimation,CATransition,CAAnimationGroup. UIView动画 U

IOS SDK详解

来源:http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html?page=1#42803301 博客专栏>移动开发专栏>IOS SDK详解 分享到:新浪微博腾讯微博IOS SDK详解 本专栏从IOS SDK中常用的Framework出发,继而深入的介绍各个Framework.每个Framework博主都会进行Demo 收藏 订阅 最新更新文章 [移动开发] IOS SDK详解之CALayer(二) 原创Blog,转载请注明出处

ios NSAttributedString 详解

ios NSAttributedString 详解 NSAttributedString可以让我们使一个字符串显示的多样化,但是目前到iOS 5为止,好像对它支持的不是很好,因为显示起来不太方便(至少没有在OS X上方便). 首先导入CoreText.framework,并在需要使用的文件中导入: #import<CoreText/CoreText.h> 创建一个NSMutableAttributedString: NSMutableAttributedString *attriString 

iOS SDK详解之IBInspectable和IB_DESIGNABLE-Storyboad动态刷新

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS-SDK详解专栏,在这里你能找到很多iOS开发基础的文章 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言: 在做应用的UI设计的时候,如果属性能够在Interface Builder的图形化界面进行设置,并且动态的预览到效果,那样无疑会大大提高应用的开发效率.而XCode为我们提供了这样的一种方式,就是使用IBInspe

iOS疯狂详解之tableview编辑添加删除

// //  VkoWLAccountVC.m //  PocketUniversity // //  Created by long on 15-1-14. //  Copyright (c) 2015年 WLong. All rights reserved. // #import "VkoWLAccountVC.h" #import "VkoWLMoreTableViewCell.h" #define kIcoArray @[@"消息",@&

iOS SDK详解之NSScanner-分析String

原创blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK详解专栏,这里有很多基础的文章 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSScanner是分析String,把String转为substring和数字的很好的工具.它使用一个NSString初始化,使用的时候通常从开头处扫描直到结尾. 本文会先举出两个例子,然后详细的讲解NSScanner的方法.源码是

iOS ASIHTTPRequest详解

ASIHTTPRequest对CFNetwork API进行了封装,并且使用起来非常简单,用Objective-C编写,可以很好的应用在Mac OS X系统和iOS平台的应用程序中.ASIHTTPRequest适用于基本的HTTP请求,和基于REST的服务之间的交互. ASIHTTPRequest功能很强大,主要特色如下: l 通过简单的接口,即可完成向服务端提交数据和从服务端获取数据的工作 l 下载的数据,可存储到内存中或直接存储到磁盘中 l 能上传本地文件到服务端 l 可以方便的访问和操作请

iOS SDK详解之NSCoding协议

原创blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=contents 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSCoding是对iOS中的Model类进行编码和解码必须要遵循的协议,如果一个对象要被归档,那么这个协议是必须的. NSCoding要实现两个方法 - initWithCoder: //解码 - enc

iOS插件详解之----CLangFormat(代码格式化管理插件)(2016.1.12王彬)

iOS插件详解之----CLangFormat(代码格式化管理)(2016.1.12王彬) 虽然在项目创建和团队组建的初期,我们就把公共约定以及一些规范定下来了,并且由于我们的代码是通过Git来做版本控制的,web上直接就支持Markdown格式的readme文件,可以随时看到最新的版本,但是这种规范只能依靠个人的意识,或者通过代码Review来解决,而且做代码Review的时候,你也不好意思总是写上一堆诸如“这里要加个空格”.“那里要加上换行”的评论吧?如果不管,久而久之,会因为每个人的习惯不