CAKeyframeAnimation 关键帧动画的用法

一、原理

之所以叫做关键帧动画是因为,这个类可以实现,某一属性按照一串的数值进行动画,就好像制作动画的时候一帧一帧的制作一样。

一般使用的时候  首先通过 animationWithKeyPath 方法 创建一个CAKeyframeAnimation实例,

 

CAKeyframeAnimation 的一些比较重要的属性

1. path

这是一个 CGPathRef  对象,默认是空的,当我们创建好CAKeyframeAnimation的实例的时候,可以通过制定一个自己定义的path来让  某一个物体按照这个路径进行动画。这个值默认是nil  当其被设定的时候  values  这个属性就被覆盖 

2. values

一个数组,提供了一组关键帧的值,  当使用path的 时候 values的值自动被忽略。

下面是一个简单的例子  效果为动画的连续移动一个block到不同的位置

    CGMutablePathRef path = CGPathCreateMutable();
    //将路径的起点定位到(50  120)  
    CGPathMoveToPoint(path,NULL,50.0,120.0);
    //下面5行添加5条直线的路径到path中
    CGPathAddLineToPoint(path, NULL, 60, 130);
    CGPathAddLineToPoint(path, NULL, 70, 140);
    CGPathAddLineToPoint(path, NULL, 80, 150);
    CGPathAddLineToPoint(path, NULL, 90, 160);
    CGPathAddLineToPoint(path, NULL, 100, 170);
    //下面四行添加四条曲线路径到path
    CGPathAddCurveToPoint(path,NULL,50.0,275.0,150.0,275.0,70.0,120.0);
    CGPathAddCurveToPoint(path,NULL,150.0,275.0,250.0,275.0,90.0,120.0);
    CGPathAddCurveToPoint(path,NULL,250.0,275.0,350.0,275.0,110.0,120.0);
    CGPathAddCurveToPoint(path,NULL,350.0,275.0,450.0,275.0,130.0,120.0);
    //以“position”为关键字
 创建 实例
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //设置path属性
    [animation setPath:path];
    [animation setDuration:3.0];
    //这句代码表示 是否动画回到原位
    //[animation setAutoreverses:YES];
    CFRelease(path);
    [self.block.layer addAnimation:animation forKey:NULL];
运行后  block会先沿着直线移动,之后再沿着设定的曲线移动,完全按照我们设定的“关键帧”移动。

    CGPoint p1=CGPointMake(50, 120);
    CGPoint p2=CGPointMake(80, 170);
    CGPoint p3=CGPointMake(30, 100);
    CGPoint p4=CGPointMake(100, 190);
    CGPoint p5=CGPointMake(200, 10);
    NSArray *values=[NSArray arrayWithObjects:[NSValue valueWithCGPoint:p1],[NSValue valueWithCGPoint:p2],[NSValue valueWithCGPoint:p3],[NSValue valueWithCGPoint:p4],[NSValue valueWithCGPoint:p5], nil];
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    [animation setValues:values];
    [animation setDuration:3.0];
    [animation setAutoreverses:YES];
    [self.block.layer addAnimation:animation forKey:NULL];

       也非常简单,到目前位置,只用到了CAKeyframeAnimation的两个关键属性就能完成动画,下面的一些属性提供了更加细致化,更加强大的功能。

设定每一帧的时间

       默认情况下,一帧动画的播放,分割 的时间是动画的总时间除以帧数减去一。你可以通过下面的公式决定每帧动画的时间:总时间/(总帧数-1)。 例如,如果你指定了一个 5 帧,10 秒的动画,那么每帧的时间就是 2.5 秒钟:10/(5-1)=2.5。你可以做更多 的控制通过使用 keyTimes 关键字,你可以给每帧动画指定总时间之内的某个时间点。 

       通过设置属性keyTimes,能实现这个功能,这个属性是一个数组,其成员必须是NSNumber。

       同时 这个属性的设定值要与calculationMode属性相结合,同时他们有一定的规则,

The appropriate values in the keyTimes array are dependent on the calculationMode property.

  • If the calculationMode is set to kCAAnimationLinear, the first value in the array must be 0.0 and the last value must be 1.0. Values are interpolated between the specified key times.

  • If the calculationMode is set to kCAAnimationDiscrete, the first value in the array must be 0.0.

  • If the calculationMode is set to kCAAnimationPaced or kCAAnimationCubicPaced, the keyTimes array is ignored。

如果keyTimes的值不合法,或者不符合上面的规则,那么就会被忽略。

[animation setCalculationMode:kCAAnimationLinear]; 
[animation setKeyTimes:[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.25], [NSNumber numberWithFloat:0.50],[NSNumber numberWithFloat:0.75], [NSNumber numberWithFloat:1.0], nil]];

calculationMode

这个属性用来设定 关键帧中间的值是怎么被计算的

可选的值有

<span style="margin: 0px; padding: 0px; ">NSString * const kCAAnimationLinear;     默认是这种模式
NSString * const kCAAnimationDiscrete;   只展示关键帧的状态,没有中间过程,没有动画。
NSString * const kCAAnimationPaced;
NSString * const kCAAnimationCubic;
NSString * const kCAAnimationCubicPaced;</span>
<span style="margin: 0px; padding: 0px; ">关键帧动画的基础步骤</span>

1.决定你想要做动画的属性(例如,框架,背景,锚点,位置,边框,等等) 

2.在动画对象值的区域中,指定开始,结束,和中间的值。这些都是你的关键帧(看清单 4-2)
3.使用 duration 这个字段指定动画的时间
4.通常来讲,通过使用 times 这个字段,来给每帧动画指定一个时间。如果你没有指定这些,核心动画就会通过你在 values 这个字段指定的值分割出时间段。

5.通常,指定时间功能来控制步调。 这些都是你需要做的。你创建你的动画和增加他们到层中。调用-addAnimation 就开始了动画。 


二、举例使用

1.使用贝赛尔曲线路径的关键帧动画

     UIBezierPath *path = [UIBezierPath bezierPath];
     [path moveToPoint:CGPointMake(-40, 100)];
     [path addLineToPoint:CGPointMake(360, 100)];
     [path addLineToPoint:CGPointMake(360, 200)];
     [path addLineToPoint:CGPointMake(-40, 200)];
     [path addLineToPoint:CGPointMake(-40, 300)];
     [path addLineToPoint:CGPointMake(360, 300)];
     
     CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
     moveAnimation.path = path.CGPath;
     moveAnimation.duration = 8.0f;
     moveAnimation.rotationMode = kCAAnimationRotateAuto;
     [shapeLayer addAnimation:moveAnimation forKey:@"moveAnimation"];

2.使用基于缩放的关键帧动画

     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
     
     CATransform3D scale1 = CATransform3DMakeScale(0.5, 0.5, 1);
     CATransform3D scale2 = CATransform3DMakeScale(1.2, 1.2, 1);
     CATransform3D scale3 = CATransform3DMakeScale(0.9, 0.9, 1);
     CATransform3D scale4 = CATransform3DMakeScale(1.0, 1.0, 1);
     
     NSArray *frameValues = [NSArray arrayWithObjects:
                             [NSValue valueWithCATransform3D:scale1],
                             [NSValue valueWithCATransform3D:scale2],
                             [NSValue valueWithCATransform3D:scale3],
                             [NSValue valueWithCATransform3D:scale4],
                             nil];
     
     [animation setValues:frameValues];
     
     NSArray *frameTimes = [NSArray arrayWithObjects:
                            [NSNumber numberWithFloat:0.0],
                            [NSNumber numberWithFloat:0.5],
                            [NSNumber numberWithFloat:0.9],
                            [NSNumber numberWithFloat:1.0],
                            nil];
     [animation setKeyTimes:frameTimes];
     
     animation.fillMode = kCAFillModeForwards;
     animation.duration = .25;
     
     [self addAnimation:animation forKey:@"DSPopUpAnimation"];

3.使用基于路径的关键帧动画

     CGMutablePathRef path = CGPathCreateMutable();
     
     CGPathMoveToPoint(path, NULL, 50.0, 120.0);
     CGPathAddCurveToPoint(path, NULL, 50.0, 275.0, 150.0, 275.0, 150.0, 120.0);
     CGPathAddCurveToPoint(path,NULL,150.0,275.0,250.0,275.0,250.0,120.0);
     CGPathAddCurveToPoint(path,NULL,250.0,275.0,350.0,275.0,350.0,120.0);
     CGPathAddCurveToPoint(path,NULL,350.0,275.0,450.0,275.0,450.0,120.0);
     
     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
     [anim setPath:path];
     [anim setDuration:3.0];
     [anim setAutoreverses:YES];
     CFRelease(path);
     [self.layer addAnimation:anim forKey:@"path"];
4.使用基于位置点的关键桢动画

     CGPoint pt0 = CGPointMake(50.0, 120.0);
     CGPoint pt1 = CGPointMake(50.0, 275.0);
     CGPoint pt2 = CGPointMake(150.0, 275.0);
     CGPoint pt3 = CGPointMake(150.0, 120.0);
     CGPoint pt4 = CGPointMake(150.0, 275.0);
     CGPoint pt5 = CGPointMake(250.0, 275.0);
     CGPoint pt6 = CGPointMake(250.0, 120.0);
     CGPoint pt7 = CGPointMake(250.0, 275.0);
     CGPoint pt8 = CGPointMake(350.0, 275.0);
     CGPoint pt9 = CGPointMake(350.0, 120.0);
     CGPoint pt10 = CGPointMake(350.0, 275.0);
     CGPoint pt11 = CGPointMake(450.0, 275.0);
     CGPoint pt12 = CGPointMake(450.0, 120.0);
     NSArray *values = [NSArray arrayWithObjects:
                        [NSValue valueWithCGPoint:pt0],
                        [NSValue valueWithCGPoint:pt1],
                        [NSValue valueWithCGPoint:pt2],
                        [NSValue valueWithCGPoint:pt3],
                        [NSValue valueWithCGPoint:pt4],
                        [NSValue valueWithCGPoint:pt5],
                        [NSValue valueWithCGPoint:pt6],
                        [NSValue valueWithCGPoint:pt7],
                        [NSValue valueWithCGPoint:pt8],
                        [NSValue valueWithCGPoint:pt9],
                        [NSValue valueWithCGPoint:pt10],
                        [NSValue valueWithCGPoint:pt11],
                        [NSValue valueWithCGPoint:pt12], nil];
     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
     [anim setValues:values];
     [anim setDuration:3.0];
     [anim setAutoreverses:YES];
     
     [self.layer addAnimation:anim forKey:@"path"];

5.使用基于旋转的关键桢动画

CAKeyframeAnimation *keyAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
             CATransform3D rotation1 = CATransform3DMakeRotation(30 * M_PI/180, 0, 0, -1);
             CATransform3D rotation2 = CATransform3DMakeRotation(60 * M_PI/180, 0, 0, -1);
             CATransform3D rotation3 = CATransform3DMakeRotation(90 * M_PI/180, 0, 0, -1);
             CATransform3D rotation4 = CATransform3DMakeRotation(120 * M_PI/180, 0, 0, -1);
             CATransform3D rotation5 = CATransform3DMakeRotation(150 * M_PI/180, 0, 0, -1);
             CATransform3D rotation6 = CATransform3DMakeRotation(180 * M_PI/180, 0, 0, -1);
             
             [keyAnim setValues:[NSArray arrayWithObjects:
                                 [NSValue valueWithCATransform3D:rotation1],
                                 [NSValue valueWithCATransform3D:rotation2],
                                 [NSValue valueWithCATransform3D:rotation3],
                                 [NSValue valueWithCATransform3D:rotation4],
                                 [NSValue valueWithCATransform3D:rotation5],
                                 [NSValue valueWithCATransform3D:rotation6],
                                 nil]];
             [keyAnim setKeyTimes:[NSArray arrayWithObjects:
                                   [NSNumber numberWithFloat:0.0],
                                   [NSNumber numberWithFloat:0.2f],
                                   [NSNumber numberWithFloat:0.4f],
                                   [NSNumber numberWithFloat:0.6f],
                                   [NSNumber numberWithFloat:0.8f],
                                   [NSNumber numberWithFloat:1.0f],
                                   nil]];
             [keyAnim setDuration:4];
             [keyAnim setFillMode:kCAFillModeForwards];
             [keyAnim setRemovedOnCompletion:NO];
             [zhiZhenLayer addAnimation:keyAnim forKey:nil];

添加动画结束的delegate

CAKeyframeAnimation* animation;
    animation = [CAKeyframeAnimation animation];
    animation.delegate = self;
    [animation setValue:@"aaa" forKey:@"TAG"];

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    NSString *strTag = [anim valueForKey:@"TAG"];
    if ([strTag isEqualToString:@"aaa"]) {
        aniIsRuning = NO;
    }
}



你可能感兴趣的:(CAKeyframeAnimation 关键帧动画的用法)