user1799795
user1799795

Reputation: 279

Multiple CALayer animations Executed at the Same time

I am trying to make an animation where two layers move to the side, scale down, and rotate a little bit in 3D, all at the same time (then move back with the layer previously at the bottom not on top). I tried several methods, but none seem to work.

I have the 3d transform animation like so:

perspectiveTransformLeft = CATransform3DIdentity;
perspectiveTransformLeft.m34 = 1.0 / 500;
perspectiveTransformLeft = CATransform3DRotate(perspectiveTransformLeft, 35.0f * M_PI / 360.0f, 0.0f, 1.0f, 0.0f);

I've tried adding a scale transform that didn't work:

perspectiveTransformLeft = CATransform3DMakeScale(0.75, 0.75, 1);

I've tried to scale the layer in an animation block, but that didn't work either:

[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options: UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     endingLayer.frame = CGRectMake(20.0f, 0.0f, 724.0f, 538.0f);
                     switchViewBottom.layer.transform = perspectiveTransformRight;
                 }
                 completion:^(BOOL finished){
                     [delegate switchAnimationFinished];
                 }
 ];

I am at a loss. Can someone help me?

Upvotes: 5

Views: 3605

Answers (1)

Vlad
Vlad

Reputation: 3366

Do some reading on CAAnimationGroup and use CABasicAnimations instead. That should held you achieve what you're after. I'll search for an example in my code (I previously used it) if you'll have issues implementing it.

Edit: Here's some code

typedef void (^animationCompletionBlock)(void);
typedef void (^animationStartedBlock)(void);

- (void)addAnimations:(NSArray *)animations withDuration:(CGFloat)animationDuration onView:(UIView *)aView {
   animationStartedBlock startBlock = ^void(void) {
      // Additional Animation start code here
   };

   animationCompletionBlock endBlock = ^void(void) {
      // Additional animation completed code here
   };

   CAAnimationGroup *group = [CAAnimationGroup animation];
   group.fillMode = kCAFillModeForwards;
   group.removedOnCompletion = NO;
   group.duration = animationDuration;
   [group setAnimations:animations];
   group.delegate = self;

   [group setValue:startBlock forKey:@"animationStartedBlock"];
   [group setValue:endBlock forKey:@"animationCompletionBlock"];

   [aView.layer addAnimation:group forKey:@"yourAnimationName"];
}

This will have your completion blocks called in your delegate

// Animation Delegate
- (void)animationDidStart:(CAAnimation *)anim {
   animationStartedBlock animationStartedBlock = [anim valueForKey:@"animationStartedBlock"];
   if (animationStartedBlock) {
      animationStartedBlock();
   }
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
   animationCompletionBlock animationCompleteBlock = [theAnimation valueForKey:@"animationCompletionBlock"];
   if (animationCompleteBlock) {
      animationCompleteBlock();
   }
}

How you create the animations and add them to an array to pass to this method is up to you, depending on what animations you want.

This is an example for two scale / fade animations:

// Scale
- (CABasicAnimation *)scaleAnimationForImageView:(UIImageView *)imageView withDuration:(CGFloat)duration {
   CGRect imageFrame = imageView.frame;
   CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
   [resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(40.0f, imageFrame.size.height * (40.0f / imageFrame.size.width))]];
   resizeAnimation.fillMode = kCAFillModeForwards;
   resizeAnimation.duration = duration;
   resizeAnimation.removedOnCompletion = NO;
   return resizeAnimation;
}

// Fade
- (CABasicAnimation *)fadeAnimationWithFinalOpacity:(CGFloat)opacity withDuration:(CGFloat)duration {
   CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
   [fadeOutAnimation setToValue:[NSNumber numberWithFloat:opacity]];
   fadeOutAnimation.fillMode = kCAFillModeForwards;
   fadeOutAnimation.removedOnCompletion = NO;
   fadeOutAnimation.duration = duration;
   return fadeOutAnimation;
}

Upvotes: 5

Related Questions