CoreAnimation 核心动画

2017-05-16  本文已影响0人  yuandiLiao

最近总结一下CoreAnimation的基本知识。。。( CALayer Animatable Properties)

Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。
Core Animation可以用在Mac OS X和iOS平台。
Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

先上一张图,看一下核心动画中的基本类和他们之间的关系,箭头表示继承关系。

WechatIMG7.jpeg

下面分一下几点介绍

1、CAAnimation

CAAnimation 是核心动画中的基础抽象类,其他的都是继承自他来使用。

CAAnimation
provides the basic support for the [CAMediaTiming] and [CAAction]protocols. 
You do not create instance of
[CAAnimation]: to animate Core Animation layers or SceneKit objects, 
create instances of the concrete subclasses [CABasicAnimation], 
[CAKeyframeAnimation], [CAAnimationGroup], or [CATransition]

CAAnimation遵循< CAMediaTiming >和< CAAction >协议,不能直接使用CAAnimation去实现动画效果,而是使用它的子类CABasicAnimation 、CAKeyframeAnimation、CAAnimationGroup、CATransition。

CAMediaTiming
可以调整动画的持续时间、重复次数、动画的速度等。

CAAction
通过响应动作的方法来实现动画
看一下CAAnimation里面的API
+ (nullable id)defaultValueForKey:(NSString *)key;
类方法:根据相对的属性key返回属性值,有点类似字典

- (BOOL)shouldArchiveValueForKey:(NSString *)key;
根据相对的属性key该属性的值返回是否可以归档。
属性(部分属性是遵循CAMediaTiming协议中的)
属性 说明
duration 动画持续的时间,默认是0
speed 速度比例,默认是1,如果调节为n,那么在动画持续时间内会加速执行n次
beginTime 开始时间 ,默认是0, 若想延迟ns,就设置为CACurrentMediaTime()+n,CACurrentMediaTime()为图层的当前时间
timeOffset 时间偏移,用来暂停动画使用
repeatCount 动画重复的次数,默认为0,无限循环可以设置HUGE_VALF或者MAXFLOAT
repeatDuration 动画重复的时间间隔,默认0
autoreverses 倒向动画,默认是NO,如果是Yes,动画正向执行后,会倒向执行一次
removedOnCompletion 默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
fillMode 决定动画开始之前或者结束之后的形态
timingFunction 速度控制函数,控制动画运行的节奏,可以使用该类中的类方法:
+ (instancetype)functionWithName:(NSString *)name;
name传入上面的类型创建一个CAMediaTimingFunction对象
fillMode属性
timingFunction属性
CAAnimation的代理方法
@interface NSObject (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. */
// 动画结束后调用
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

@end

2.CAPropertyAnimation

CAPropertyAnimation继承自CAAnimation,也是一个抽象类,是CABasicAnimation和CAKeyframeAnimation的父类,不能直接使用来生成动画效果。

keyPath

通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。

/* Creates a new animation object with its `keyPath' property set to
 * 'path'. */

+ (instancetype)animationWithKeyPath:(nullable NSString *)path;

/* The key-path describing the property to be animated. */

@property(nullable, copy) NSString *keyPath;
keyPath类型 动画效果
transform.rotation.z Z轴旋转
transform.rotation.x X轴旋转
transform.rotation.y Y轴旋转
transform.scale.x 宽的比例转换
transform.scale.y 高的比例转换
opacity 透明度
backgroundColor 背景色
anchorPoint 定位点,锚点,默认中心点(0.5, 0.5)
borderColor 边框颜色
borderWidth 边框宽度
bounds 大小
contents 内容
contentsRect 内容矩形
cornerRadius 圆角
frame 位置
hidden 隐藏
mask 标记
maskToBounds 切割
position 位置
shadowOffset 阴影偏移
shadowColor 阴影颜色
shadowRadius 阴影角度
shadowOpacity 阴影透明度
strokeEnd 颜色从无到有
strokeStart 颜色从有到无

3.CABasicAnimation 基本动画

继承自CAPropertyAnimation,基本动画。主要的效果是keyPath里面的,指定keyPath相应属性的初始值和keyPath相应属性的结束值。然后执行动画。

keyPath类型 动画效果
fromValue keyPath相应属性的初始值
toValue keyPath相应属性的结束值

动画过程说明:
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue。
keyPath内容是CALayer的可动画Animatable属性。

如果fillMode = kCAFillModeForwards同时removedOnComletion = NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
fillMode = kCAFillModeForwards同时removedOnComletion = NO要同时设定才有效

-(void)createCAAnimation
{
    //核心动画是作用在CALayer层的,所以先创建一个layer来承载动画
    CALayer *layer = [[CALayer alloc] init];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    //layer没有center的属性,而是position
    layer.position = self.view.center;
    layer.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5].CGColor;
    [self.view.layer addSublayer:layer];
    
    //创建一个CAAnimation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    //属性
    //动画持续的时间,默认是0 ,    animation.duration = 5;
    //速度比例,默认是1,如果调节为n,那么在动画持续时间内会加速执行n次
    animation.speed = 1;
    //开始时间 ,默认是0,若想延迟ns,就设置为CACurrentMediaTime()+n,CACurrentMediaTime()为图层的当前时间
    animation.beginTime = 0;
    //时间偏移,用来暂停动画使用
    animation.timeOffset = 0;
    //动画重复的次数,默认为0,无限循环可以设置HUGE_VALF或者MAXFLOAT
    animation.repeatCount = 0;
    //动画重复的时间间隔,默认0
    animation.repeatDuration = 0;
    //倒向动画,默认是NO,如果是Yes,动画正向执行后,会倒向执行一次
    animation.autoreverses = NO;
    //默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
    animation.removedOnCompletion = YES;
    //决定动画开始之前或者结束之后的形态
    animation.fillMode = kCAFillModeRemoved;
    //速度控制函数,控制动画运行的节奏
    CAMediaTimingFunction *timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.timingFunction = timingFunction;
    //开始
    animation.fromValue = @(M_PI);
    //结束
    animation.toValue = @(M_PI/4);
    //为layer加上动画
    [layer addAnimation:animation forKey:@"ANIMATION"];
}

4. CAKeyframeAnimation 关键帧动画

和CABasicAnimation一样继承自CAPropertyAnimation,可以理解为CABasicAnimation的升级版。

属性 说明
values NSArray对象。里面的元素称为“关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
path 可以设置一个CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path只对CALayer的anchorPoint和position起作用。如果设置了path,那么values将被忽略
keyTimes 可以为对应的关键帧指定对应的时间点,每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的
timingFunctions 每个帧的运动类型,NSArray中存放CAMediaTimingFunction对象,个数要比values中的少一个。因为动画的真实个数要比设置的value少一个。
calculationMode 该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似
rotationMode
calculationMode
rotationMode
-(void)createValuesAnimation
{
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //设置路径
    keyframeAnimation.values = [[NSArray alloc] initWithObjects:
                                [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.center.y)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.origin.y+89)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.origin.y+89)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.center.y)],
                                 [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.size.height-25)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.size.height-25)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],

                                nil];
    //整个动画的时长
    keyframeAnimation.duration = 10;
    //每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同
    keyframeAnimation.keyTimes = @[@(0),@(0.2),@(0.4),@(0.5),@(0.55),@(0.7),@(0.9),@(1)];
    keyframeAnimation.repeatCount = MAXFLOAT;
    [self.layer addAnimation:keyframeAnimation forKey:nil];
    [self.view.layer addSublayer:self.layer];

}
-(void)createPathAnimation
{
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];

    //创建一个路径
    CGMutablePathRef path = CGPathCreateMutable();
    //添加圆形
    //CGPathAddEllipseInRect(path, NULL, CGRectMake(50, 90, 200, 200));
    //矩形
    CGPathAddRect(path, NULL, CGRectMake(50, 90, 200, 200));

    //设置路径
    keyframeAnimation.path = path;

    //释放路径
    CGPathRelease(path);
    
    //设置动画时间
    keyframeAnimation.duration = 3;
    //原路线返回
    // keyframeAnimation.autoreverses = YES;
      keyframeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    
    //设置重复次数
    keyframeAnimation.repeatCount = MAXFLOAT;
    //匀速kCAAnimationCubicPaced
    keyframeAnimation.calculationMode = kCAAnimationCubicPaced;
    [self.layer addAnimation:keyframeAnimation forKey:nil];
    [self.view.layer addSublayer:self.layer];
}

5.CATransition 转场动画

继承自CAAnimation,切换页面的动画。

属性 说明
type 动画类型下面会列出各种类型
subtype 方向
startProgress 从什么地方开始动画,默认动画0到1
endProgress 从什么地方结束动画,默认动画0到1
type 说明
开放的四种基本效果
kCATransitionPush 推入效果
kCATransitionMoveIn 移入效果
kCATransitionReveal 截开效果
kCATransitionFade 渐入渐出效果
私有的效果
cube 方块
suckEffect 三角
rippleEffect 水波抖动
pageCurl 上翻页
pageUnCurl 下翻页
oglFlip 上下翻转
cameraIrisHollowOpen 镜头快门开
cameraIrisHollowClose 镜头快门关
subtype的类型
- (void)push
{
    //创建一个转场动画
    CATransition *stansition = [CATransition animation];
    //设置动画时间
    stansition.duration = 1;
    //设置类型
    stansition.type = @"cube";
    stansition.subtype = kCATransitionFromRight;
    //添加动画
    [self.navigationController.view.layer addAnimation:stansition forKey:nil];
    
    NextViewController *nextVC = [[NextViewController alloc] init];
    [self.navigationController pushViewController:nextVC animated:YES];  
}

6.CAAnimationGroup 动画组

多个动画的组合,即可以把多个动画放在animations数组中,然后同时执行多个动画。

-(void)createAnimationGroup
{
    //创建一个动画组
    CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
    //动画时间,如果动画组中的时间没有设置是不行的,如果设置了动画组的时间,然后里面的动画没有设置时间, 那么则以动画组的时间为准,如果里面的具体动画也设置了时间,那么以具体的动画设置的时间为准
    animationGroup.duration = 10;
    //创建一个基础动画
    CABasicAnimation *basicAnimaiton = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
    basicAnimaiton.toValue = @(M_PI);
    
    //创建一个帧动画
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //设置路径
    keyframeAnimation.values = [[NSArray alloc] initWithObjects:
                                [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.center.y)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.origin.y+89)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.origin.y+89)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.center.y)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.origin.x+25, self.view.frame.size.height-25)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width-25, self.view.frame.size.height-25)],
                                [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y)],
                                
                                nil];
    //每个动画的时长,总时长为1,然后运动到那个点是,该点在总时长的百分之几,和valus个数相同
    keyframeAnimation.keyTimes = @[@(0),@(0.2),@(0.4),@(0.5),@(0.55),@(0.7),@(0.9),@(1)];
    //将两个动画添加到动画组中
    animationGroup.animations = @[basicAnimaiton,keyframeAnimation];
    [self.layer addAnimation:animationGroup forKey:nil];
    [self.view.layer addSublayer:self.layer];
}

上一篇下一篇

猜你喜欢

热点阅读