QuartzCore和CoreAnimation

相关资源

GitHub粒子发射和复制图层示例
GitHub粘性控件示例
GitHub弹性动画
CALayer分析
响应者手势分析
CAEmitter分析

QuartzCore 简介

本文档集合提供了核心动画的API参考。核心动画为应用程序提供动画和显示层次结构功能。有关详细信息,请参见 Core Animation Programming Guide

QuartzCore主要结构

  1. CoreAnimation
  2. CADisplayLink定时器
  3. CALayer 及其子类(参考上方链接)
  4. CAMediaTiming协议相关
  5. CATransaction事物相关
  6. CATransform3D

可以看出所有的类和协议都以CA开头,所以可以把此框架认为就是核心动画框架

CoreAnimation简介

CoreAnimation在APP中的结构.png

核心动画本身并不是绘图系统。它是一个在硬件层面合成和操纵您的应用程序的内容的基础设施。在此基础设施的核心是CALayer对象,层用于管理和操作内容。一个图层捕获你的内容到一个位图中,位图可以很容易地被图形硬件使用。在大多数应用中,层是用来管理View内容的,但也可以根据需要创建独立独立的层使用。

CoreAnimation基本使用思路
CoreAnimation1.png

其实还有一个孙子类CASpringAnimation,它继承自CABasicAnimation,是用来做弹性动画的。其实很多动画UIKit中也有相关的API(包括弹性动画),至于使用哪一种动画:

  1. UIView动画与核心动画的区别?
  • 核心动画只作用在layer.
  • 核心动画修改的值都是假像.它的真实位置没有发生变化,不会改变layer的frame、transform属性.
  1. 什么时候用UIView动画什么时候用核心动画?
  • 当需要与用户进行交互时用UIView,不需要与用户进行交互时两个都可以。
  1. 什么情况用核心动画最多?
  • 转场动画(UIView的转场动画类型比较少).
  • 帧动画.
  • 动画组.

CAAnimation使用

所有的核心动画形式都定义在这个CAAnimation.h头文件中

开发步骤:
  1. 首先得有CALayer(因为CoreAnimation是作用在CALayer上的
  2. 初始化一个CAAnimation对象,并设置一些动画相关属性
  3. 通过调用CALayer的addAnimation:forKey:方法,增加CAAnimation对象到CALayer中,这样就能开始执行动画了
  4. 通过调用CALayer的removeAnimationForKey:方法可以停止CALayer中的动画
CAMediaTiming协议

简介:这个协议对于核心动画很重要。它提供对动画节奏时间的控制的API。 Layers and Animations都遵守并实现了协议方法。这个协议建立了分层的定时系统定时系统,每个对象描述的时间值都是映射自其parent。
Tip:animation的parent是groupAnimation,再往上是UILayer,再往上是layer.superLayer。下面会举例一个属性分析。

CAMediaTiming属性

/* 动画开始的时间,所有类型对象的该值都是0,它好像是一个相对值:举例:假如layer.beginTime = 1,图层上的动画animation.beginTime = CACurrentMediaTime() + 2 ,那么这个动画被加入之后就会延迟1+2=3秒钟开始执行*/
@property CFTimeInterval beginTime;

/* Specifies the basic duration of the animation, in seconds. */
@property CFTimeInterval duration;

/* 运动速度,如果该值是2,那么该动画的速度将会是parent类的2倍 默认值是 1*/
@property float speed;

/*timeOffset和beginTime类似,但是和增加beginTime导致的延迟动画不同,增加timeOffset只是让动画快进到某一点,例如,对于一个持续1秒的动画来说,设置timeOffset为0.5意味着动画将从一半的地方开始。默认值0 */
@property CFTimeInterval timeOffset;

/* The repeat count of the object. May be fractional. Defaults to 0. */
@property float repeatCount;

/* The repeat duration of the object. Defaults to 0. */
@property CFTimeInterval repeatDuration;

/* 反向执行动画. Defaults to NO. */
@property BOOL autoreverses;

/* 动画执行完事之后,应该怎么处理,如下选项
CA_EXTERN NSString * const kCAFillModeForwards
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCAFillModeBackwards
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCAFillModeBoth
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
CA_EXTERN NSString * const kCAFillModeRemoved
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);
 Defaults to 'removed'. */
@property(copy) NSString *fillMode;

CACurrentMediaTime()
Returns the current CoreAnimation absolute time.
这个确实不好理解,不过我们可以通过测试总结:

  1. 他从动画产生被添加到Layer上记录一个时间a;
  2. 如果动画是被beginTime 延迟了2秒,但是它的值是a+=2;
  3. 如果动画被暂停了3(speed = 0),a还是会按系统时钟走下去a+=3;
    所以CACurrentMediaTime()这个时间非常关键
CALayer上动画的暂停和恢复
- (void)pauseLayer {
    CALayer *layer = self.redView.layer;
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    // 让CALayer的时间停止走动
    layer.speed = 0.0;
    // 让CALayer的时间停留在pausedTime这个时刻
    layer.timeOffset = pausedTime;
}

- (void)resumeLayer {
    CALayer *layer = self.redView.layer;
    CFTimeInterval pausedTime = layer.timeOffset;
    // 1. 让CALayer的时间继续行走
    layer.speed = 1.0;
    // 2. 取消上次记录的停留时刻
    layer.timeOffset = 0.0;
    // 3. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime)
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    // 4. 设置相对于父坐标系的开始时间(往后退timeSincePause)
    NSLog(@"Resume---- %f",timeSincePause);
    layer.beginTime += timeSincePause;
}
CAAnimation

是所有核心动画对象的父类

/* 动画节奏控制,默认线性动画 */
@property(nullable, strong) CAMediaTimingFunction *timingFunction;

/* 动画执行过程代理 */
@property(nullable, strong) id <CAAnimationDelegate> delegate;

/*动画执行完毕是否从Layer上移除,默认YES;如果不想移除动画最终状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
 */
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

// CAAnimationDelegate方法(可选)
/* Called when the animation begins its active duration. */
- (void)animationDidStart:(CAAnimation *)anim;
/* 当动画完成了它的执行时间或者被移除了,这个方法会被调用. 'flag'is true if the animation reached the end of its active duration
 without being removed. */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
CAPropertyAnimation

CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation

/* 通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@“position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果 */
@property(nullable, copy) NSString *keyPath;
CABasicAnimation
// keyPath相应属性的初始值
@property(nullable, strong) id fromValue;
// keyPath相应属性的结束值
@property(nullable, strong) id toValue;
/ /keyPath相应属性的过渡值
@property(nullable, strong) id byValue;
CAKeyframeAnimation

关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:CAKeyframeAnimation对keyPath可以使用多值,而且支持路线Path

// 里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧。
@property(nullable, copy) NSArray *values;

/* 可选属性,定义了动画功能的行为,非空值就会覆盖Values属性*/
@property(nullable) CGPathRef path;

/* 可选,定义了动画的节奏(NSNumber类型)。每个值对应values里的每一个值,取值[0,1]。比如:values中有三个值,keyTimes = @[@0.2,@0.5,@0.8],则在duration*0.2开始从value0执行动画,在duration*0.9到value2并等待uration*0.1时间之后结束动画 */
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;

// 对应values,加入values有n个keyframes,那么就需要n-1个timingFunctions,它描述keyframe到keyframe的时间节奏。
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;
CASpringAnimation

弹性动画,继承CABasicAnimation

/* 附在弹簧末端的物体的质量。必须大于0,默认值是1. */
@property CGFloat mass;

/* 弹簧刚度系数。必须大于0, Defaults to 100. */
@property CGFloat stiffness;

/* 阻尼系数, 必须大于或者等于0,Defaults to 10. */
@property CGFloat damping;

/* 附在弹簧上的物体的初速度,默认值0,代表没有移动;负值表示网固定点反方向运动,正值反之 */
@property CGFloat initialVelocity;

/* 返回弹簧系统在静止时所需的估计时间。 时间是在当前系数下预估的。 */
@property(readonly) CFTimeInterval settlingDuration;
CAAnimationGroup

动画组,动画组,是CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行,属性beginTime刚才也提到了,具有累加的效果。

CATransition

转场动画,CATransition是CAAnimation的子类,用于做转场动画。UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果。

/* 转场动画类型,Defaults to `fade'. */
@property(copy) NSString *type;

/* 转场动画子类型 */
@property(nullable, copy) NSString *subtype;

/* The amount of progress through to the transition at which to begin and end execution. Legal values are numbers in the range [0,1]。endProgress(默认值1)值必须要大于startProgress(默认值0)。*/
@property float startProgress;
@property float endProgress;

/* 执行过度的可选过滤器,一旦设置`type' and `subtype'设置被忽略. The filter must implement `inputImage', `inputTargetImage' and `inputTime' input keys, and the `outputImage' output key. Optionally it may support the `inputExtent' key, which will be set to a rectangle describing the region in which the transition should run. Defaults to nil. */
@property(nullable, strong) id filter;
TransitionType.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容