当前位置: 首页>移动开发>正文

iOS动画-CAAnimation的说明与简单使用

CAAnimation是QuartzCore框架里面定义的

CAAnimation主要是遵循了 CAMediaTiming 协议,拥有了一些动画的属性

属性 参数类型 备注
beginTime CFTimeInterval 指定动画开始的时间。(设置动画beginTime为1,动画将延时1秒后开始执行)
duration CFTimeInterval 动画时长;(默认值为0,但是实际动画默认持续时间为0.25秒)
speed float 动画执行的速度;(默认值为0,减少它会减慢动画的时间,增加它会加快速度)(设置speed为2时,则动画实际执行时间是duration的一半)
timeOffset CFTimeInterval 动画时间偏移量;(设置时长3秒动画的timeOffset为1时,动画会从1秒位置执到最后,再执行之前跳过的部分)
repeatCount float 重复的次数。不停重复设置为 HUGE_VALF
repeatDuration CFTimeInterval 设置动画的时间。在该时间内动画一直执行,不计次数。
autoreverses BOOL 动画结束时是否执行逆动画 ,动画从初始值执行到最终值,是否会反向回到初始值;(设置为YES,动画完成后将以动画的形式回到初始位置)
fillMode NSStrinng 决定当前对象在非动画时间端段的动画属性值,如动画开始之前和动画结束之后
timingFunction CAMediaTimingFunction 设置动画的速度变化
fromValue id 所改变属性的起始值
toValue id 所改变属性的结束时的值
byValue id 所改变属性相同起始值的改变量
removedOnCompletion BOOL 动画完成之后是否还原,默认为yes。

一些常用的animationWithKeyPath值的总结

使用形式 备注
transform.scale @(0.8) 比例转化,在所有方向上进行缩放
transform.scale.x @(0.8) 宽的比例
transform.scale.y 高的比例 @(0.8)
transform.rotation.x 围绕x轴旋转 @(M_PI)
transform.rotation.y 围绕y轴旋转 @(M_PI)
transform.rotation.z 围绕z轴旋转 @(M_PI)
cornerRadius 圆角的设置 @(50)
backgroundColor 背景颜色的变化 (id)[UIColor grayColor].CGColor
bounds 中心不变,改变大小 [NSValue valueWithCGRect:CGRectMake(0, 0, 50, 50)];
position 中心改变) [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents 改变内容,比如UIImageView的图片 imageAnima.toValue = (id)[UIImage imageNamed:@"name"].CGImage;
opacity 透明度 @(0.6)
contentsRect.size.width 横向拉伸缩放 @(0.3)最好是0~1之间的
contentsRect.size.height 纵向拉伸缩放 @(0.3)最好是0~1之间的

核心动画Core Animation常用类的继承关系

动画类 动画特性
CAMediaTiming 协议;定义了一段动画内用于控制时间的属性的集合
CAAnimation 抽象类;作为所有动画类型父类,不可直接使用
CAPropertyAnimation 抽象类;作为基础动画和帧动画的父类,不可直接使用
CABasicAnimation 基础动画;用于实现单一属性变化的动画
CAKeyFrameAnimation 关键帧动画;用于实现单一属性连续变化的动画
CAAnimaitionGroup 组动画;用于实现多属性同时变化的动画
CATrasition 转场过渡动画;

CAMediaTiming只有这两个代理方法 顾名思义,一个开始一个结束,CAAnimation实现代理方法不同于其他,CAAnimation不用声明CAAnimationDelegate。直接重写方法即可

/* Delegate methods for CAAnimation. */

@protocol CAAnimationDelegate <NSObject>
@optional

/* 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. */
//动画结束的回调 。flag参数表明了动画是自然结束还是被打断的
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

@end

1.CABasicAnimation
通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
2.CAKeyframeAnimation
Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动
3.CAAnimationGroup
Group也就是组合的意思,就是把对这个Layer的所有动画都组合起来。PS:一个layer设定了很多动画,他们都会同时执行,
4.CATransition
这个就是苹果帮开发者封装好的一些动画,

KeyFrame的意思是关键帧,所谓“关键”就是改变物体运动趋势的帧,在该点处物体将发生运动状态,比如矩形的四个角,抛物线的顶点等。

values 指明整个动画过程中的关键帧点
path 与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略。
keyTimes 是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....
timeFunctions 这个属性用以指定时间函数,类似于运动的加速度,有以下几种类型。记住,这是一个数组,你有几个子路径就应该传入几个元素
/** Timing function names. **/

CA_EXTERN NSString * const kCAMediaTimingFunctionLinear
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//默认,匀速执行动画
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseIn
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//浅入,先慢慢加速,后突然停止
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseOut
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//先全速开始,再慢慢减速停止
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseInEaseOut
    CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);//浅入浅出,先慢慢加速,再慢慢减速
CA_EXTERN NSString * const kCAMediaTimingFunctionDefault
    CA_AVAILABLE_STARTING (10.6, 3.0, 9.0, 2.0);//效果同KCAMediaTimingFuncationEaseInEaseOut

calculationMode 该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似

/* `calculationMode' strings. */

CA_EXTERN CAAnimationCalculationMode const kCAAnimationLinear
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//线性,默认
CA_EXTERN CAAnimationCalculationMode const kCAAnimationDiscrete
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃的出现在各个关键帧上
CA_EXTERN CAAnimationCalculationMode const kCAAnimationPaced
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));//平均,keyTimes和Timing functions设置失效
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubic
    API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));//平均,同上
CA_EXTERN CAAnimationCalculationMode const kCAAnimationCubicPaced
    API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));//平均,同上

/* `rotationMode' strings. */

CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAuto
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
CA_EXTERN CAAnimationRotationMode const kCAAnimationRotateAutoReverse
    API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

示例

实现水波动画

- (void)drawRect:(CGRect)rect {
     //新建动画数组
    CALayer *animationLayer = [CALayer layer];
    CAAnimationGroup *animationGroup = [self animationGroupAnimations:[self animationArray]];
    CALayer *pulsingLayer = [self pulsingLayer:rect animationGroup:animationGroup];
    //将动画 Layer 添加到 animationLayer
    [animationLayer addSublayer:pulsingLayer];
    
    // 新建缩放动画
    CABasicAnimation *animationTwo = [self oppositeScaleAnimation];
    // 新建一个动画 Layer,将动画添加上去
    CALayer *pulsingLayerTwo = [self pulsingLayer:rect animation:animationTwo];
    //将动画 Layer 添加到 animationLayer
    [animationLayer addSublayer:pulsingLayerTwo];
    [self.layer addSublayer:animationLayer];
}

- (CALayer *)pulsingLayer:(CGRect)rect animation:(CABasicAnimation *)animation {
    CALayer *pulsingLayer = [CALayer layer];
    pulsingLayer.borderWidth = 0.5;
    pulsingLayer.borderColor = [[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor;
    pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
    pulsingLayer.cornerRadius = rect.size.height / 2;
    [pulsingLayer addAnimation:animation forKey:@"plulsing"];
    return pulsingLayer;
}

- (CALayer *)pulsingLayer:(CGRect)rect animationGroup:(CAAnimationGroup *)animationGroup {
    CALayer *pulsingLayer = [CALayer layer];
    pulsingLayer.borderWidth = 1;
    pulsingLayer.borderColor = [[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor;
    pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
    pulsingLayer.cornerRadius = rect.size.height / 2;
    [pulsingLayer addAnimation:animationGroup forKey:@"plulsing"];

    return pulsingLayer;
}

- (CAAnimationGroup *)animationGroupAnimations:(NSArray *)array {
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.beginTime = CACurrentMediaTime();
    animationGroup.duration = 2;
    animationGroup.repeatCount = 2;
    animationGroup.autoreverses = YES;//动画结束时是否执行逆动画
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];//设置动画的速度变化:淡出
    animationGroup.removedOnCompletion
    return animationGroup;
}


- (NSArray *)animationArray {
    NSArray *animationArray = nil;
    CABasicAnimation *scaleAnimation = [self scaleAnimation];
    CAKeyframeAnimation *borderColorAnimation = [self borderColorAnimation];
    animationArray = @[scaleAnimation, borderColorAnimation];
    return animationArray;
}

- (CABasicAnimation *)scaleAnimation {
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
     
    scaleAnimation.fromValue = @1;
    scaleAnimation.toValue = @3;
    return scaleAnimation;
} 

- (CABasicAnimation *)oppositeScaleAnimation {
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = @1;
    scaleAnimation.toValue = @0.7;
    scaleAnimation.beginTime = CACurrentMediaTime();
    scaleAnimation.duration = 2;
    scaleAnimation.repeatCount = 2;
    scaleAnimation.autoreverses = YES;//动画结束时是否执行逆动画
    scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];//设置动画的速度变化:淡出
    return scaleAnimation;
}

- (CAKeyframeAnimation *)borderColorAnimation {
    CAKeyframeAnimation *borderColorAnimation = [CAKeyframeAnimation animation];
    borderColorAnimation.keyPath = @"borderColor";
    borderColorAnimation.values = @[
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.4].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.3].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.2].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.1].CGColor,
        (__bridge id)[[UIColor whiteColor]colorWithAlphaComponent:0.0].CGColor];
    borderColorAnimation.keyTimes = @[@0.2,@0.4,@0.6,@0.8,@1
    ];
    return borderColorAnimation;
}

引用、借鉴

iOS动画-CAAnimation使用详解https://www.jianshu.com/p/c22918a5e7ca
简书发表文章格式(MakrDwon使用)https://www.jianshu.com/p/0e63982d7a98


https://www.xamrdz.com/mobile/4rd1848567.html

相关文章: