iOS开发之中级iOS DeveloperiOS程序猿

QuartzCore和CoreAnimation

2017-05-05  本文已影响278人  asaBoat

相关资源

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动画与核心动画的区别?
  1. 什么时候用UIView动画什么时候用核心动画?
  1. 什么情况用核心动画最多?

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
上一篇下一篇

猜你喜欢

热点阅读