Animate custom CALayer properties inside a CATransaction

Until now I've been able to animate the custom properties of my CALayer subclass, thanks to + (BOOL)needsDisplayForKey:(NSString *)key and CABasicAnimations .

However it turns out that chaining animations can become very tricky because all the code takes place in a single animationDidStop:finished: method.

So I wanted to switch to CATransactions since they support the new block syntax, which would allow me to specify a completion block with + (void)setCompletionBlock:(void (^)(void))block .

But it appears to me that CATransaction can only animate the so-called 'animatable properties' and it doesn't work with my custom layer properties, even with the needsDisplayForKey: method implemented.

So is there a way to make custom properties in a CALayer to animate with CATransaction ?

EDIT: My intent is to do something along the lines:

[CATransaction begin];
[CATransaction setAnimationDuration:0.5];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
    NSLog(@"blabla");
}];

myLayer.myProperty = newValue;

[CATransaction commit];

The update of myProperty value to newValue is not animated. I've tried to implement actionForLayer:forKey: in the view managing myLayer to return a CABasicAnimation . But actionForLayer:forKey: is never called with the key myProperty . And yes, myLayer is not view.layer but a sublayer, and yes I set the delegate of myLayer to the containing view.


I believe, based on my reading of some source code, that you can still use a CABasicAnimation within the CATransaction . Any CAAnimations added between the [CATransaction begin] and [CATransaction commit] should be a part of the transaction.

[CATransaction begin];
[CATransaction setAnimationDuration:0.5];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
    NSLog(@"blabla");
}];

// Create the CABasicAnimation using your existing code
CABasicAnimation *myPropertyAnim = [CABasicAnimation animationWithKeyPath:@"myProperty"];
// TODO: Setup animation range
myPropertyAnim.toValue = newValue;

// The CATransaction does not observe arbitrary properties so this fails:
//myLayer.myProperty = newValue;

// Add the CAAnimation subclass during the CATransaction
[myLayer addAnimation:myPropertyAnim forKey:@"myKey"];

[CATransaction commit];

Apologies that I don't have a project setup to easily test this now, but I believe it will work.

Check these site for the code:

  • http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/9/22_FLIPPIN_OUT_AT_NSVIEW.html
  • http://boondoggle.atomicwang.org/lemurflip/MFFlipController.m
  • Code that I referenced:

    [CATransaction begin];
    [topLayer addAnimation:topAnimation forKey:@"flip"];
    [bottomLayer addAnimation:bottomAnimation forKey:@"flip"];
    [CATransaction commit];
    

    There's a great class called CAAnimationBlocks, and explained here, that is a category on CAAnimation that allows you to use completion blocks like you would on a UIView.

    You use it simply by calling:

    CABasicAnimation myAnimation;
    [myAnimation setCompletion:^(BOOL finished) { // Do something }];
    
    链接地址: http://www.djcxy.com/p/74178.html

    上一篇: CALayer / CABasicAnimation不透明度动画缓存?

    下一篇: 在CATransaction中动画自定义CALayer属性