Search code examples
iosobjective-ccore-animation

How can I know current animation in CAAnimationGroups?


Now I want to use Core Animation to write some methods for animation just as easy as Cocos2d ,just like ccMove,ccFade,ccRotate.

Everything seems ok, but when I want to implement the animation sequence,I've troubled.The first thing I've thought was CCAnimationGroup,but when animations in groups,I can not kown when the current action complete, so I can't set the property of layer, this lead to the layer back to the original status. Anyone know this ? My code:

    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
    testView.backgroundColor= [UIColor redColor];
    testView.center = self.view.center;
    //mark1: textview's position is self.view.center
    [self.view addSubview:testView];

    CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation 
        animationWithKeyPath:@"position"];
    moveAnimation.duration = 3;
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 100, 100);
    CGPathAddLineToPoint(path, NULL, 200, 200);
    moveAnimation.path = path;
    //mark2: I want the testview move to CGPointMake(100,200)
    CGPathRelease(path);   

    CABasicAnimation *angleAnimation = 
        [CABasicAnimation 
          animationWithKeyPath:@"transform.rotation"];
    angleAnimation.toValue = @(45 * M_PI / 180);
    angleAnimation.duration = 3;
    angleAnimation.beginTime = 3;  //make3: rotate testview 45°

    CAAnimationGroup *actionGroup = [CAAnimationGroup animation];
    [actionGroup setDuration:6];
    [actionGroup setAnimations:@[moveAnimation, angleAnimation]];

    [CATransaction begin];

    [testView.layer addAnimation:actionGroup forKey:nil];

    [CATransaction commit];

You can run it, and you'll see the textview's position and rotate is not I want.

Can someone help me?


Solution

  • I've solved it.In fact,I don't need to know when one of the actions in group complete.Just set the animation's fillMode and removedOnCompletion, so that the the layer would not back to original status.

    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
    testView.backgroundColor= [UIColor redColor];
    testView.center = self.view.center;
    [self.view addSubview:testView];   //mark1: textview's position is self.view.center
    
    CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAnimation.duration = 3;
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 100, 100);
    CGPathAddLineToPoint(path, NULL, 200, 200);
    moveAnimation.path = path;
    moveAnimation.fillMode = kCAFillModeForwards;
    moveAnimation.removedOnCompletion = NO;
    CGPathRelease(path);    //mark2: I want the testview move to CGPointMake(100,200)
    
    CABasicAnimation *angleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    angleAnimation.toValue = @(45 * M_PI / 180);
    angleAnimation.duration = 3;
    angleAnimation.beginTime = 3;  //make3: rotate testview 45°
    angleAnimation.fillMode = kCAFillModeForwards;
    angleAnimation.removedOnCompletion = NO;
    
    CAAnimationGroup *actionGroup = [CAAnimationGroup animation];
    [actionGroup setDuration:6];
    [actionGroup setAnimations:@[moveAnimation, angleAnimation]];
    actionGroup.fillMode = kCAFillModeForwards;
    actionGroup.removedOnCompletion = NO;
    
    [CATransaction begin];
    
    [testView.layer addAnimation:actionGroup forKey:nil];
    
    [CATransaction commit];
    

    In code above, I set all the action's fillmode to kCAFillModeForwards, and removedOnCompletion = NO.This just work. And I also find that scaleAnimation and fadeAnimation should set their fillmode to kCAFillModeBoth so that the layer cannot back to original property status.

    You can also check the code on my github.https://github.com/Vienta/SSAnimation Thank you!