简体   繁体   中英

iPhoneSDK Setting CALayer.transform does not work after animation is finished

I have a CALayer object. In viewDidLoad: I set a transform to it using layer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI/8.0, 0, 0, 1); This works.

After loading, I apply a CAKeyframeAnimation to animate the rotation of that layer. It also works and animation finishes correctly. To prevent the layer from removing the animation after completion I use

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

All of this works fine. But a problem occurs when I try to change the transform again (without animation) layer.transform = CATransform3DRotate(CATransform3DIdentity, M_PI/8.0, 0, 0, 1); . Nothing happens. Layer doesn't change its transform to what I have specified. If I run the animation again, the animation will happen. But cannot change the transform property without animation.

Any help is appreciated..

First of all, why are you avoiding removing the animation upon completion? You don't need these two lines,

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

since you are actually setting the layer's transform property. Those two lines are what you would use if all you wanted was the final visual state after the animation while keeping the transform the same as the original (which frankly I've never had a use for).

The next thing you have to realize is that you are setting the transform to the same value twice. Setting the transform on a layer is not additive by default. What I mean is that while you are expecting it to take your first transform and concatenating the same transform again from the final transform state, it doesn't work that way with the code you're using. You won't see a change because you're setting the state to the state it already has.

I haven't tried it, but I think that you could probably take the first transform and concatenate the new one. Something like:

layer.transform = CATransform3DRotate(layer.transform, M_PI/8.0, 0, 0, 1);

Notice how I'm starting from the current transform on the layer (first parameter of CATransform3DRotate), instead of identity. Give that a try. If it doesn't work, try something like:

layer.transform = CATransform3DConcat(layer.transform, 
                             CATransform3DMakeRotation(M_PI/8.0, 0, 0, 1));

OK, I managed to get this working. What I did was setting the layer.tranform just after calling [layer addAnimation:] . In that way, after the animation is finished, the layer will stay in the desired position as it is. Here is my code:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.repeatCount = 1;
animation.duration = 3.0;
animation.fromValue = [NSNumber numberWithDouble:currentRotationAngle];
animation.toValue = [NSNumber numberWithDouble:newRotationAngle];

[layer addAnimation:animation forKey:@"rotationAnimation"];
[layer setAffineTransform:CGAffineTransformMakeRotation(newRotationAngle)];

The problem I had was using layer.removedOnCompletion and layer.fillemode . I don't have to use them. In the new way the layer will display the layer using the layer.transform after animation is complete. CAAnimations only update the layer's presentationLayer (which maintains the layer's visual state) while animating. When the animation is finished, it will revert the layer's visual state to the one imposed by layer.transform .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM