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 23:05:23 +0000
Hi, I've used jQuery, but I don't understand the relevance or what you
mean?
On 19 Mar 2009, at 22:30, mm w wrote:
you should really create a html page and play for instance with jQuery
to understand how those mechanisms/API have been designed, and when
you will
understand what you are doing you will welcome to come again
Cheers!
On Thu, Mar 19, 2009 at 3:26 PM, Memo Akten <email@hidden> wrote:
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
--
-mmw
_______________________________________________
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