一、前言
之前做的动画都比较简单,用UIView的自带动画就能实现,最近接到一些稍微复杂的动画,于是回顾了Core Animation的一些知识,本章主要回顾下Core Animation的一些基础知识
二、Core Animation的类图和常用字段及方法
A、先看下基类:CAAnimation
First:在详细讲解基类之前先来看下CAAnimation所遵循的协议 CAMediaTiming 这里不做讲解,只需要知道:
1、CALayer和CAAnimation都遵循了该协议。
2、该协议的属性都有一个默认值【这对理解CAAnimation的+defaultValueForKey:方法很有用】
Second: 再来看下动画自定义时间函数CAMediaTimingFunction
//线性动画
kCAMediaTimingFunctionLinear
//淡入
kCAMediaTimingFunctionEaseIn
//淡出
kCAMediaTimingFunctionEaseOut
//淡入淡出
kCAMediaTimingFunctionEaseInEaseOut
//默认
kCAMediaTimingFunctionDefault
Third:看一下CAAnimationDelegate代理
/* Called when the animation begins its active duration. */
/* 监测动画开始的时间点 */
- (void)animationDidStart:(CAAnimation *)anim;
/* Called when the animation either completes its active duration or
* is removed from the object it is attached to (i.e. the layer). 'flag'
* is true if the animation reached the end of its active duration
* without being removed. */
/* 监测动画停止的时间点 1、flag==true 说明动画完成 2、flag==false 说明动画被移除 */
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
CAAnimation
@interface CAAnimation : NSObject
{
@private
void *_attr;
uint32_t _flags;
}
/* Creates a new animation object. */
/* 通过类方法创建一个CAAnimation对象
CAAnimation是一个动画抽象类,但是不要直接使用CAAnimation类,而是使用它的子类,
如上图所示展示的就是它的家族成员子类们,CAAnimation遵守CAMediaTiming和CAAction协议,它是直接作用在CALayer上的,并非UIView上,
动画执行过程不在主线程上进行,所以不会阻塞主线程。先来看看CAnimation都定义了哪些属性,方法。
*/
+ (instancetype)animation;
/* Animations implement the same property model as defined by CALayer.
* See CALayer.h for more details. */
/*注意这里是类方法:
这里相当于对一些属性的默认值进行了拦截,可以在自定义的子类中重写该方法,重新设置默认值,
比如 我自定义一个动画类
@interface LYCACustomAnimation : CABasicAnimation
这里 动画时间属性 duration 的默认值是0,我想把自定义类的这个属性默认值更改为1.0,可以这么实现
+ (id)defaultValueForKey:(NSString *)key {
if ([key isEqualToString:@"duration"]) {
return [NSNumber numberWithDouble:1.0];
}
return [super defaultValueForKey:key];
}
*/
+ (nullable id)defaultValueForKey:(NSString *)key;
/*注意这里是对象方法
判断一个key是否能被归档, 可以理解为当前类对象是否包含“key”属性*/
- (BOOL)shouldArchiveValueForKey:(NSString *)key;
/* A timing function defining the pacing of the animation. Defaults to
* nil indicating linear pacing. */
/* 动画的时间函数 */
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
/* The delegate of the animation. This object is retained for the
* lifetime of the animation object. Defaults to nil. See below for the
* supported delegate methods. */
/* 监测动画开始和结束的时间点 */
@property(nullable, strong) id delegate;
/* When true, the animation is removed from the render tree once its
* active duration has passed. Defaults to YES. */
/* 这个属性用来控制动画运行结束之后 是否从渲染树中移除当前layer,默认是YES【移除】
一般我们想让动画停留在动画的的终点状态,可以把这个属性设置为NO
*/
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
@end
总结:
1、CAAnimation是一个动画抽象类,但是不要直接使用CAAnimation类,而是使用它的子类,画执行过程不在主线程上进行,所以不会阻塞主线程;
2、可以通过重写defaultValueForKey方法更改一些属性的默认值;
3、可以使用动画的时间函数 CAMediaTimingFunction 控制一些简单的动画效果;
4、通过代理监测动画的开始、结束时间;
5、通过removedOnCompletion控制动画结束后是否从渲染树中移除;
CAPropertyAnimation 这里主要对keyPath做一些归纳
KeyPath | 描述 | 值 |
---|---|---|
transform.scale | 比例变化 | 0 ~ 1 |
transform.scale.x | 宽比例变化 | 0 ~ 1 |
transform.scale.y | 宽比例变化 | 0 ~ 1 |
transform.rotation.x | 围绕X轴旋转 | 0 ~ 2*M_PI |
transform.rotation.y | 围绕Y轴旋转 | 0 ~ 2*M_PI |
transform.rotation.z | 围绕Z轴旋转 | 0 ~ 2*M_PI |
cornerRadius | 圆角变化 | 0 ~ 2*MAX(width,height) |
backgroundColor | 颜色变化,透明度不变 | AnyColor.cgColor |
opacity | 透明度变化 | 0 ~ 1 |
bounds | 大小变化,中心不变 | CGRect |
position | 中心变化 | CGPoint |
position.x | 中心X变化 | CGFloat |
position.y | 中心Y变化 | CGFloat |
contents | 内容变化 如ImageView.image | image.cgImage |
borderWidth | 边框宽 | 0 ~ |
@interface CAPropertyAnimation : CAAnimation
...
/* additive【添加、附加】 default NO
设置一个抖动的动画:如下
_animView = [[UIView alloc] initWithFrame:CGRectMake(150, 100, 40, 40)];
tranferAnim.values = @[@0,@100,@(-100),@100,@0];
tranferAnim.keyTimes = @[@0,@(1/6.),@(3/6.),@(5/6.),@1];
tranferAnim.additive = YES;
等价于
CGFloat x = self.animView.center.x;
tranferAnim.values = @[@(x),@(x+100),@(x-100),@(x+100),@(x)];
tranferAnim.keyTimes = @[@0,@(1/6.),@(3/6.),@(5/6.),@1];
tranferAnim.additive = NO;
[self.animView.layer addAnimation:tranferAnim forKey:nil];
解释:【个人的理解,有不对之处欢迎指正】
YES 会把当前改变的值附加到presentLayer的value,presentLayer.keyPath.value = modeLayer.keyPath.value + changeValue;
NO 会把当前改变的值设置为presentLayer的value,presentLayer.keyPath.value = changeValue;
*/
@property(getter=isAdditive) BOOL additive;
/*
cumulative【累积的】设置动画是否是累加效果 default NO
该属性常与repeatCount一起使用,当设置为YES的时候动画会在上一次的基础上进行,而不是回到初始位置
例如:
CABasicAnimation *tranferAnim = [CABasicAnimation animationWithKeyPath:@"position.x"];
tranferAnim.duration = 2.0;
tranferAnim.fromValue = [NSNumber numberWithDouble:25];
tranferAnim.toValue = [NSNumber numberWithDouble:100];
tranferAnim.repeatCount = 3;
tranferAnim.cumulative = YES;
*/
@property(getter=isCumulative) BOOL cumulative;
/* 该属性值是一个CAValueFunction对象,该对象负责对属性改变的插值计算,系统已经提供了默认的插值计算方式,因此一般无须指定该属性。 */
@property(nullable, strong) CAValueFunction *valueFunction;
@end