Search code examples
iosuiviewanimationuiviewanimation-curve

Use two different UIViewAnimationCurves in the same animation


I want to be able to use one UIViewAnimationCurve for rotations and another for changes in position. Is this possible?

For example (in pseudo code);

// Begin animations

// Set rotation animation curve to EaseInOut

// Set position animation curve to Linear

// Make some changes to position

// Make some change to the angle of rotation

// Commit the animations

EDIT: (CAAnimationGroup approach suggested below) - Have created 2 separate CABasicAnimations and a CAAnimationGroup however the animations are not starting. Any ideas?

CABasicAnimation *postionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
postionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
postionAnimation.toValue = [NSValue valueWithCGPoint:[self transformPointToWorldSpaceFromViewSpace:self.spriteView.position]];
postionAnimation.delegate = self;

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.z"];
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotationAnimation.toValue = [NSNumber numberWithFloat:self.spriteView.angle -= M_PI_2];
rotationAnimation.delegate = self;

CAAnimationGroup *animationsGroup = [CAAnimationGroup animation];
animationsGroup.duration = self.clockSpeed;
animationsGroup.animations = [NSArray arrayWithObjects:postionAnimation, rotationAnimation, nil];

// Perform the animation
[self.spriteView.layer addAnimation:animationsGroup forKey:nil];

Solution

  • Your best bet is to use multiple calls to animateWithDuration:delay:options:animations:completion:. Use a different animation curve in each call, and they will run in parallel. Or, with different delay values, you can make them run in sequence.

    The code might look like this:

    [UIView animateWithDuration: .5 
      delay: 0
      options: UIViewAnimationOptionCurveEaseInOut 
      animations: ^{
        view1.center = CGPointMake(x, y);
      }
      completion:  ^{
        //code that runs when this animation finishes
      }
    ];
    
    [UIView animateWithDuration: .5 
      delay: .5
      options: UIViewAnimationOptionCurveLinear
      animations: ^{
        view2.center = CGPointMake(x2, y2);
      }
      completion:  ^{
        //code that runs when this animation finishes
      }
    ];
    

    If you use CAAnimationGroups, there are several problems.

    First, the animation group determines the animation curve for the entire group. I don't think you can specify different curves for each sub animation (although I confess I haven't tried it.)

    Secondly, if you add animations to a group, the delegates to the individual animations don't get called. Only the animation group's delegate methods get called.