Re: problems with CAAnimation - SOLVED (kinda)
Re: problems with CAAnimation - SOLVED (kinda)
- Subject: Re: problems with CAAnimation - SOLVED (kinda)
- From: Memo Akten <email@hidden>
- Date: Thu, 19 Mar 2009 22:26:03 +0000
Hi Matt, thanks for lengthy reply. At this point, I"ve only tried the
first part, and I cannot get it to use the time I'm supplying in the
animation, basically its just doing an implicit animation not
explicit. It doesn't matter whether I setValue before or after the
addAnimation.
Actually I ended up writing the generic code below. If I apply the
CAAnimationGroup as a group (i.e. bApplyIndividually = NO), then it
doesn't work at all for some reason, the values from the
layer.presentationLayer do not represent what I am seeing so a lot of
snapping going on if I apply animations before the previous one is
finished. If I only use the CAAnimationGroup as a glorified array and
apply all animations individually then all my animations are applied
correctly. So I think this is my solution. I do find it strange that I
had to resort to this (writing my own AnimationGroup!), and this
behavior is not built in. Thanks for all the tips and help.
(P.S. this assumes that all the animations in the CAAnimationGroup are
CABasicAnimations).
void applyBasicAnimation(CALayer *layer, CABasicAnimation *animation,
BOOL bApply) {
animation.fromValue = [layer.presentationLayer
valueForKeyPath:animation.keyPath];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeBoth;
NSLog(@"applyBasicAnimation forLayer:%@ key:%@ currentValue:%@",
layer.name, animation.keyPath, animation.fromValue);
if(bApply) [layer addAnimation:animation forKey:animation.keyPath];
}
void applyAnimationGroup(CALayer *layer, CAAnimationGroup
*animationGroup, NSString* key, BOOL bApplyIndividually) {
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeBoth;
for(id animation in animationGroup.animations)
applyBasicAnimation(layer, animation, bApplyIndividually);
if(!bApplyIndividually) [layer addAnimation:animationGroup
forKey:key];
}
On 19 Mar 2009, at 18:07, Matt Long wrote:
I'll address the issue with the animation ignoring your duration
first. Try placing your addAnimation call before the
setValue:forKeyPath. Let me know if that works. Also, you will
*need* to specify a fromValue in your animation. If you want the
current value (in the case where an animation is already running),
get it from the presentationLayer, e.g. [[layer presentationLayer]
valueForKeyPath@"transform.scale"]; This is the "in-flight" value.
Now let me try to clarify what I mean with the derived layer. Say
you've declared a layer called RolloverLayer that inherits from
CALayer. Calling animationForKey will return the default animation
for the keyPath you specify in the key. If you override it, *you*
determine what animation to use. It would look something like this:
- (CAAnimation *)animationForKey:(NSString *)key
{
if ([key isEqualToString:@"transform.scale"] )
{
CABasicAnimation *growAnimation = [[CABasicAnimation
animationWithKeyPath:@"transform.scale"] retain];
growAnimation.duration = 5; // very slow
// Need from value here
growAnimation.fromValue = [[self presentationLayer]
valueForKeyPath:@"transform.scale"];
growAnimation.toValue = [[[CardManager instance] config]
objectForKey:@"cardHoverScale"];
growAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
return growAnimation;
}
else if ([key isEqualToString:@"position"])
{
CABasicAnimation *postiionAnimation = [CABasicAnimation
animationWithKeyPath:@"position"];
positionAnimation.fromValue = [[self presentationLayer]
position];
positionAnimation.toValue = // etc...
}
// .........
else
{
return [super animationForKey:key];
}
}
Now, when you have one of your derived layers in use, you can do this:
// Assuming it's tied to a button or something
- (IBAction)animate:(id)sender
{
// rolloverLayer is a RolloverLayer ivar
[rolloverLayer setValue:[[[CardManager instance] config]
objectForKey:@"cardHoverScale"] forKeyPath:@"transform.scale"];
[rolloverLayer setPosition:CGPointMake(x,y)];
// etc.
}
Your overridden animationForKey will get called to get the proper
animation.
HTH,
-Matt
p.s. if you want to know when an animation has completed, set the
layer's delegate to your app delegate and then implement -
(void)animationDidStop:(CAAnimation *)theAnimation finished:
(BOOL)flag . The flag field tells you whether or not it stopped by
interruption or by run completion. YES means it completed its run,
NO means it was interrupted.
On Mar 19, 2009, at 11:09 AM, Memo Akten wrote:
Hi Matt, yea it is a bit complex, but it seems to me that what I am
trying to do is actually quite simple:
- when I rollover a layer, it animates position, scale, rotation
and alpha.
- when I rollout, it animates back.
- if I rollover, then midanimation, rollout again, it should
animate back to original position *from where it was at the moment
I rolled out*, NOT snapping to the hover position (which is why I
can't use FromValues).
I also would like the animation to be EaseInEaseOut and know when
the animation is complete - which is why I'm using CAAnimation, so
I can use delegate - instead of using implicit animation.
Going back to what you were saying, I'm afraid I don't full
understand. So I extend CALayer? How would I use animationForKey?
Does that not only return the animation for a given arbitrary key?
Also I tried the code below, and unfortunately the animation
happened very quickly, not 5 seconds at all...
growAnimation = [[CABasicAnimation
animationWithKeyPath:@"transform.scale"] retain];
growAnimation.duration = 5; // very slow
growAnimation.toValue = [[[CardManager instance] config]
objectForKey:@"cardHoverScale"];
growAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[rootLayer setValue:[[[CardManager instance] config]
objectForKey:@"cardHoverScale"] forKeyPath:@"transform.scale"];
[rootLayer addAnimation:growAnimation forKey:@"transform.scale"];
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden