CABasicAnimation not changing its position propert

2020-07-10 08:03发布

问题:

i am applying CABasicAnimation for position property of a layer it is animating well but after animation complete its coming back to original position how to avoid that and to make image to stay in animated position only?

回答1:

There are a few different ways to solve this. My favorite is to set the object at the end of the animation, and use fromValue instead of toValue to create the animation. You can also set both fromValue and toValue to create this effect. ie

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:@"slide"];

The other way to do this is to set yourself as the delegate and implement:

-(void)animationDidStop:(id)sender finished:(BOOL)finished {
     viewToAnimate.center = endPoint;
}


回答2:

You need to set the final position. If you only use the animation fromValue and toValue it will snap back to the original starting point. The animation uses a copy of the view/layer as it "plays" and then the animation will show the original view/layer when it finishes.

If you don't explicitly set it, it will appear to snap back, even though the view/layer never really moved.

startPoint and endPoint are CGPoints and myView is the UIView that is being animated.

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.duration = .3;
    animation.fromValue = [NSValue valueWithCGPoint:startPoint];
    animation.toValue = [NSValue valueWithCGPoint:endPoint];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [myView.layer addAnimation:animation forKey:@"position"];   
    myView.layer.position = endPoint;   // Must set end position, otherwise it jumps back


回答3:

To set the object at the end of the animation just write the code like this

#import <QuartzCore/QuartzCore.h>

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:easing];
animation.fillMode = kCAFillModeForwards;  // This line will stop the animation at the end position of animation
animation.autoreverses = NO;

viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:@"slide"];


回答4:

You can just set removedOnCompletion to NO if you want to preserve the final value. And don't forget to set the fillMode.

Swift 4+

animation.fillMode = .forwards;  
animation.isRemovedOnCompletion = false

Objective-C

animation.fillMode = kCAFillModeForwards;  //The receiver remains visible in its final state when the animation is completed.
animation.removedOnCompletion = NO;


回答5:

If you look at the docs for addAnimation:forKey:, it says 'Typically this is implicitly invoked'. In other words, you're not supposed to call it directly. You're actually meant to do the following instead, which is even easier than setting from and to values, you simply set the values directly on the layer:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = .3;

myLayer.actions = @{@"opacity": animation};
myLayer.opacity = 0;

This will fade a layer to zero opacity.