iOS CAKeyFrameAnimation Scaling Flickers at animation end

后端 未结 3 2178
刺人心
刺人心 2021-02-06 12:29

In another test of Key Frame animation I am combining moving a UIImageView (called theImage) along a bezier path and scaling larger it as it moves, resulting in a 2

3条回答
  •  别那么骄傲
    2021-02-06 13:13

    CAAnimations will flicker at the end if the terminal state was assigned in such a way that it itself created an implicit animation. Keep in mind CAAnimations are temporary adjustments of an object properties for the purposes of visualizing transition. When the animation done, if the layer's state is still the original starting state, that is what is going to be displayed ever so temporarily until you set the final layer state, which you do in your animationDidStop: method.

    Furthermore, your animation is adjusting the bounds.size property of your layer, so you should similarly set your final state rather than using the transform adjustment as your final state. You could also use the transform property as the animating property in the animation instead of bounds.size.

    To remedy this, immediately after assigning the animation, change the layer's permeant state to your desired terminal state so that when the animation completes there will be no flicker, but do so in such a manner to no trigger an implicit animation before the animation begins. Specifically, in your case you should do this at the end of your animation set up:

    UIImageView* theImage = ....
    float scaleFactor = 2.0;
    ....
    
    theImage.center = destination;
    theImage.transform = CGAffineTransformMakeScale(1.0,1.0);
    
    CGSize finalSize = CGSizeMake(theImage.image.size.height*scaleFactor, theImage.image.size.width*scaleFactor);
    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
    [resizeAnimation setToValue:[NSValue valueWithCGSize:finalSize]];
    resizeAnimation.fillMode = kCAFillModeBackwards;
    resizeAnimation.removedOnCompletion = NO;  
    
    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    pathAnimation.path = [jdPath path].CGPath;
    pathAnimation.fillMode = kCAFillModeBackwards;
    pathAnimation.removedOnCompletion = NO;
    
    CAAnimationGroup* group = [CAAnimationGroup animation];
    group.animations = [NSArray arrayWithObjects:pathAnimation, resizeAnimation, nil];
    group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    group.removedOnCompletion = NO;
    group.duration = duration;
    group.delegate = self;
    
    [theImage.layer addAnimation:group forKey:@"animateImage"];
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    theImage.bounds = CGRectMake( theImage.bounds.origin.x, theImage.bounds.origin.y, finalSize.width, finalSize.height );
    [CATransaction commit];
    

    and then remove the transform adjustment in your animationDidStop: method.

提交回复
热议问题