博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CAAnimation 系列动画
阅读量:6166 次
发布时间:2019-06-21

本文共 15323 字,大约阅读时间需要 51 分钟。

CAAnimation继承关系

    引用官方文档:

Core Animation provides high frame rates and smooth animations without burdening the CPU and slowing down your app. Most of the work required to draw each frame of an animation is done for you. You configure animation parameters such as the start and end points, and Core Animation does the rest, handing off most of the work to dedicated graphics hardware, to accelerate rendering. For more details, see .

    Core Animation提供了高帧率和流畅的动画,而不会加重CPU负担,也不会减慢应用程序的速度。你可以配置动画参数,如起始点和结束点,Core animation完成其余部分,将大部分工作交给专用的图形硬件,以加速渲染。

    对于CAAnimation,是核心动画基础类,不直接使用,一般用它的子类。CAAnimation有三个子类CAPropertyAnimation、CATransition、CAAnimationGroup。第二个CATransition是转场动画,第三个CAAnimationGroup是动画组。第一个CAPropertyAnimation又分为两个子类CABasicAnimation、CAKeyframeAnimationCAKeyframeAnimation是关键帧动画。CABasicAnimation下面还有个子类CASpringAnimation是弹簧动画。

    CAPropertyAnimation通过animationWithKeyPath来创建动画,可以看看有哪些属性可以创建动画。详见

anchorPointbackgroundColorbackgroundFiltersborderColorborderWidthboundscompositingFiltercontentscontentsRectcornerRadiusdoubleSidedfiltersframehiddenmaskmasksToBoundsopacitypositionshadowColorshadowOffsetshadowOpacityshadowPathshadowRadiussublayerssublayerTransformtransformzPosition复制代码

CAKeyframeAnimation 关键帧动画

    可以使用继承的animationWithKeyPath:方法创建一个CAKeyframeAnimation对象,并指定要在层上动画的属性的关键路径。然后可以指定用于控制时间和动画行为的关键帧值。对于大多数动画类型,可以使用值和keyTimes属性指定关键帧值。在动画期间,Core animation通过在您提供的值之间插入来生成中间值。当动画一个坐标点(例如layer的位置)的值时,你可以指定该点的路径,而不是单独的值。动画的节奏由你提供的时间信息控制。

重要属性

属性 描述
values 用来存放关键帧的数组
path 基于点的属性的路径。
keyTimes 对应关键帧段的时间点的NSNumber数组
timingFunctions 关键帧动画节奏的数组,比如快进慢出、慢进快出等
calculationMode 确定沿路径动画的对象是否旋转以匹配路径切线
tensionValues 定义曲线的紧密性的NSNumber数组
continuityValues 定义时间曲线锐角的NSNumber数组
biasValues 定义曲线相对于控制点的位置的NSNumber数组
Rotation Mode Values rotationMode属性使用这些常量
Value calculation modes calculationMode属性使用这些常量

效果代码

#pragma mark - 指定keyPath为position,通过Values来创建关键帧动画- (void)CAKeyframeAnimationWithValues{    CGFloat margin = 50.f;    CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];    animation.keyPath = @"position";    NSValue * value0 = [NSValue valueWithCGPoint:CGPointMake(margin, margin)];    NSValue * value1 = [NSValue valueWithCGPoint:CGPointMake(margin, SCREENHEIGHT - margin)];    NSValue * value2 = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH - margin, SCREENHEIGHT - margin)];    NSValue * value3 = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH - margin, margin)];    NSValue * value4 = [NSValue valueWithCGPoint:CGPointMake(margin, margin)];    animation.values = @[value0,value1,value2,value3,value4];    //当我们动画完成时,如果希望动画就自动移除的话,我们可以设置此属性为YES,默认值为YES    animation.fillMode = kCAFillModeForwards;    animation.removedOnCompletion = NO;    animation.duration = 4;    animation.repeatCount = MAXFLOAT;    //快入快出    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];    [self.pointView.layer addAnimation:animation forKey:@"position.values"];}#pragma mark - 指定keyPath为position,通过path路径来创建关键帧动画- (void)CAKeyframeAnimationWithPath{    CGFloat margin = 50.f;    CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];    animation.keyPath = @"position";    CGMutablePathRef path = CGPathCreateMutable();    CGPathAddRect(path, NULL, CGRectMake(margin, margin, SCREENWIDTH - margin * 2, SCREENHEIGHT - margin * 2));    animation.path = path;    CGPathRelease(path);    animation.fillMode = kCAFillModeForwards;    animation.removedOnCompletion = NO;    animation.duration = 4;    animation.repeatCount = MAXFLOAT;    NSMutableArray * timingFunctionArray = [NSMutableArray new];    for (NSInteger i = 0 ; i < 5 ; i ++)    {        //每一段都是快出效果        CAMediaTimingFunction * timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];        [timingFunctionArray addObject:timingFunction];    }        animation.timingFunctions = timingFunctionArray;    [self.pointView.layer addAnimation:animation forKey:@"position.path"];}复制代码

效果图

    需要注意的是removedOnCompletion设置为NO的时候,不需要layer的时候要根据key手动移除动画。

[self.pointView.layer removeAnimationForKey:@"position.values"];[self.pointView.layer removeAnimationForKey:@"position.path"];复制代码

CATransition 转场动画

    CATransition的父类是CAAnimation,和CAPropertyAnimationCAAnimationGroup同级。CATransition是用来视图的转场动画。

You can transition between a layer's states by creating and adding a CATransition object to it. The default transition is a cross fade, but you can specify different effects from a set of predefined transitions.

重要属性

属性 描述
startProgress 整个变形接收的起点
endProgress 整个变形接收的终点
type 指定转换类型
subtype 转换方向的子类型
filter 提供转换的图像过滤器对象
Common Transition Types 指定可以与type属性一起使用的转换类型的常量
Common Transition Subtypes 指定可以与subtype属性一起使用的转换类型的常量

效果代码

    其中typesubtype有官方指定的类型

/* Common transition types. */CA_EXTERN NSString * const kCATransitionFadeCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionMoveInCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionPushCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionRevealCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);/* Common transition subtypes. */CA_EXTERN NSString * const kCATransitionFromRightCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionFromLeftCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionFromTopCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);CA_EXTERN NSString * const kCATransitionFromBottomCA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0);复制代码

    还有几种效果是私有API,在官方文档中找不到,慎用

Cube,                     //立体SuckEffect,               //吮吸OglFlip,                  //翻转RippleEffect,             //波纹PageCurl,                 //翻页PageUnCurl,               //反翻页CameraIrisHollowOpen,     //开镜头CameraIrisHollowClose,    //关镜头复制代码

    这里写了一个例子,有12种type转场效果和4种subtype转场方向,用枚举来封装一下

typedef NS_ENUM(NSInteger,CATransactionType) {    CATransactionType_Fade = 0,                 //默认    CATransactionType_MoveIn,                   //覆盖    CATransactionType_Push,                     //推入    CATransactionType_Reveal,                   //揭开    CATransactionType_Cube,                     //立体    CATransactionType_SuckEffect,               //吮吸    CATransactionType_OglFlip,                  //翻转    CATransactionType_RippleEffect,             //波纹    CATransactionType_PageCurl,                 //翻页    CATransactionType_PageUnCurl,               //反翻页    CATransactionType_CameraIrisHollowOpen,     //开镜头    CATransactionType_CameraIrisHollowClose,    //关镜头};- (void)CATransitionWithType:(NSString *)type WithSubtype:(NSString *)subtype{    CATransition * animation = [CATransition animation];    animation.duration = 2.f;    animation.type = type;    animation.subtype = subtype;    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];    [self.view.layer addAnimation:animation forKey:nil];}- (void)btnClick:(UIButton *)sender{    UIButton * lastBtn;    NSInteger index = sender.tag - 100;    if (index > 11)    {        lastBtn = (UIButton *)[self.view viewWithTag:_subtype + 100];        [lastBtn setBackgroundImage:[self createImageWithColor:self.subtypeNormalColor] forState:UIControlStateNormal];        [sender setBackgroundImage:[self createImageWithColor:self.subtypeSelectedColor] forState:UIControlStateNormal];        _subtype = index;    }    else    {        lastBtn = (UIButton *)[self.view viewWithTag:_transactionType + 100];        [lastBtn setBackgroundImage:[self createImageWithColor:self.typeNormalColor] forState:UIControlStateNormal];        [sender setBackgroundImage:[self createImageWithColor:self.typeSelectedColor] forState:UIControlStateNormal];        _transactionType = index;    }    NSString * subtypeString ;    switch (_subtype % 4) {        case 0:            subtypeString = kCATransitionFromTop;            break;        case 1:            subtypeString = kCATransitionFromBottom;            break;        case 2:            subtypeString = kCATransitionFromLeft;            break;        case 3:            subtypeString = kCATransitionFromRight;            break;        default:            break;    }    switch (_transactionType) {        case CATransactionType_Fade:            [self CATransitionWithType:kCATransitionFade WithSubtype:subtypeString];            break;        case CATransactionType_MoveIn:            [self CATransitionWithType:kCATransitionMoveIn WithSubtype:subtypeString];            break;        case CATransactionType_Push:            [self CATransitionWithType:kCATransitionPush WithSubtype:subtypeString];            break;        case CATransactionType_Reveal:            [self CATransitionWithType:kCATransitionReveal WithSubtype:subtypeString];            break;        case CATransactionType_Cube:            [self CATransitionWithType:@"cube" WithSubtype:subtypeString];            break;        case CATransactionType_SuckEffect:            [self CATransitionWithType:@"suckEffect" WithSubtype:subtypeString];            break;        case CATransactionType_OglFlip:            [self CATransitionWithType:@"oglFlip" WithSubtype:subtypeString];            break;        case CATransactionType_RippleEffect:            [self CATransitionWithType:@"rippleEffect" WithSubtype:subtypeString];            break;        case CATransactionType_PageCurl:            [self CATransitionWithType:@"pageCurl" WithSubtype:subtypeString];            break;        case CATransactionType_PageUnCurl:            [self CATransitionWithType:@"pageUnCurl" WithSubtype:subtypeString];            break;        case CATransactionType_CameraIrisHollowOpen:            [self CATransitionWithType:@"cameraIrisHollowOpen" WithSubtype:subtypeString];            break;        case CATransactionType_CameraIrisHollowClose:            [self CATransitionWithType:@"cameraIrisHollowClose" WithSubtype:subtypeString];            break;        default:            break;    }    static NSInteger i = 0;    self.bgView.image = i % 2 ? [UIImage imageNamed:@"拉姆.jpeg"] :[UIImage imageNamed:@"蕾姆.jpeg"];    i ++;}复制代码

效果图


CAAnimationGroup 动画组

    分组动画在CAAnimationGroup实例指定的时间中运行。分组动画的持续时间不会被缩放到他们的CAAnimationGroup的持续时间。相反,动画被剪切到动画组的持续时间。例如,在一个动画组中分组的10秒动画,持续时间为5秒,只显示动画的前5秒。

效果代码

#pragma mark - 一个红包雨的例子- (void)showRain{    UIImageView * imageV = [UIImageView new];    imageV.image = [UIImage imageNamed:@"page"];    imageV.frame = CGRectMake(0, 0, 50 , 50 );    CALayer * layer = [CALayer layer];    layer.bounds = imageV.frame;    layer.contents = (id)imageV.image.CGImage;    layer.anchorPoint = CGPointMake(0, 0);    layer.position = CGPointMake(0, 0);    [self.view.layer addSublayer:layer];    [self addAnimationWithLayer:layer];}- (void)addAnimationWithLayer:(CALayer *)layer{    int height = [UIScreen mainScreen].bounds.size.height;    int width = [UIScreen mainScreen].bounds.size.height;    CAKeyframeAnimation * moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];    NSValue * A = [NSValue valueWithCGPoint:CGPointMake(arc4random() % width, 0)];    NSValue * B = [NSValue valueWithCGPoint:CGPointMake(arc4random() % width, height + 100)];    moveAnimation.values = @[A,B];    moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];    CAKeyframeAnimation * tranAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];    CATransform3D r0 = CATransform3DMakeRotation(M_PI/180 * (arc4random() % 360 ) , 0, 0, -1);    CATransform3D r1 = CATransform3DMakeRotation(M_PI/180 * (arc4random() % 360 ) , 0, 0, -1);    tranAnimation.values = @[[NSValue valueWithCATransform3D:r0],[NSValue valueWithCATransform3D:r1]];    tranAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];    CAAnimationGroup * group = [[CAAnimationGroup alloc] init];    group.duration = arc4random() % 200 / 100.0 + 3.5;    group.fillMode = kCAFillModeForwards;    group.removedOnCompletion = NO;    group.animations = @[moveAnimation,tranAnimation];    [layer addAnimation:group forKey:nil];}复制代码

效果图


CASpringAnimation 弹簧动画

    CASpringAnimation的父类是CABasicAnimation, CABasicAnimation可以看成是只有头尾有值的关键帧动画。

You would typically use a spring animation to animate a layer's position so that it appears to be pulled towards a target by a spring. The further the layer is from the target, the greater the acceleration towards it is. CASpringAnimation allows control over physically based attributes such as the spring's damping and stiffness.

    CASpringAnimation是基于物理的属性控制,比如弹簧的阻尼和刚度。

重要属性

属性 描述
damping 定义弹簧运动如何受到阻尼的影响
initialVelocity 初速度
mass 连接到弹簧末端的物体的质量
settlingDuration 预估静止时间
stiffness 弹簧刚度系数

效果代码

- (void)btnClick:(UIButton *)sender{    //frame属性不可动画化 只能通过 bounds 和 position完成    CASpringAnimation * animation = [CASpringAnimation animationWithKeyPath:@"bounds"];    //质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大    animation.mass = self.massSlider.value;    //刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快    animation.stiffness = self.stiffnessSlider.value;    //阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快    animation.damping = self.dampingSlider.value;    //初始速率,动画视图的初始速度大小;速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反    animation.initialVelocity = self.velocitySlider.value;    animation.duration = 3.f;    animation.fromValue =  [NSValue valueWithCGRect:CGRectMake(0, 0, 80, 100)];    animation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 80, 240)];    animation.removedOnCompletion = NO;    animation.fillMode = kCAFillModeForwards;    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];    [self.baseView.layer addAnimation:animation forKey:nil];    CASpringAnimation * animation1 = [CASpringAnimation animationWithKeyPath:@"position"];    animation1.duration = 3.f;    animation1.fromValue = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH / 2 , 250)];    animation1.toValue = [NSValue valueWithCGPoint:CGPointMake(SCREENWIDTH / 2 , 250 - 70)];    animation1.removedOnCompletion = NO;    animation1.fillMode = kCAFillModeForwards;    [self.baseView.layer addAnimation:animation1 forKey:nil];}复制代码

效果图


UIView的弹簧动画

另外在看看cell上用UIView Block弹簧动画的特效

效果代码

+ (void)animateWithDuration:(NSTimeInterval)duration                      delay:(NSTimeInterval)delay     usingSpringWithDamping:(CGFloat)dampingRatio      initialSpringVelocity:(CGFloat)velocity                    options:(UIViewAnimationOptions)options                 animations:(void (^)(void))animations                 completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);复制代码
- (void)cellAnimation{    [self.springTableView reloadData];    NSArray * cellArrays = self.springTableView.visibleCells;    CGFloat height = self.springTableView.bounds.size.height;    for (UITableView * cell in cellArrays)    {        cell.transform = CGAffineTransformMakeTranslation(-SCREENWIDTH, height);    }    for (NSInteger i = 0 ; i < cellArrays.count ; i ++ )    {        UITableViewCell * cell = (UITableViewCell *)cellArrays[i];        [UIView animateWithDuration:1.5                              delay:0.05 * i             usingSpringWithDamping:0.8              initialSpringVelocity:0                            options:0 animations:^{                    cell.transform = CGAffineTransformMakeTranslation(0, 0);            } completion:nil];    }}复制代码

效果图

转载地址:http://bmuba.baihongyu.com/

你可能感兴趣的文章
4.3.3版本之引擎bug
查看>>
SQL Server表分区详解
查看>>
STM32启动过程--启动文件--分析
查看>>
垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
查看>>
淘宝的几个架构图
查看>>
linux后台运行程序
查看>>
Oracle中drop user和drop user cascade的区别
查看>>
登记申请汇总
查看>>
Android Jni调用浅述
查看>>
(二)Spring Boot 起步入门(翻译自Spring Boot官方教程文档)1.5.9.RELEASE
查看>>
Shell基础之-正则表达式
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
售前工程师的成长---一个老员工的经验之谈
查看>>
Get到的优秀博客网址
查看>>
Python学习--time
查看>>
在OSCHINA上的第一篇博文,以后好好学习吧
查看>>
Spring常用注解
查看>>
linux:yum和apt-get的区别
查看>>
Sentinel 1.5.0 正式发布,引入 Reactive 支持
查看>>