-->

Animate CALayer hide

2019-04-09 23:18发布

问题:

I'm trying to hide a CALayer after a few microseconds and I'm using CABasicAnimation to animate the hide.

At the moment I'm trying to use

[aLayer setHidden:YES];

CABasicAnimation * hideAnimation = [CABasicAnimation animationWithKeyPath:@"hidden"];
[hideAnimation setDuration:aDuration];
[hideAnimation setFromValue:[NSNumber numberWithBool:NO]];
[hideAnimation setToValue:[NSNumber numberWithBool:YES]];
[hideAnimation setBeginTime:0.09];
[hideAnimation setRemovedOnCompletion:NO];
[hideAnimation setDelegate:self];

[alayer addAnimation:hideAnimation forKey:@"hide"];

But when I run this, the layer is hidden immediately, rather than waiting for the desired beginTime.

I'm uncertain about my keyPath as "hidden" but couldn't find any other option and the documentation does state that the hidden property of a CALayer is animatable.

What's the correct way to achieve what I'm looking for?

回答1:

Try animating the opacity property instead. Go from 1.0 to 0.0 and you should get the effect you want.



回答2:

From CAMediaTiming.h, it says about beginTime property:

The begin time of the object, in relation to its parent object, if applicable. Defaults to 0.

You should use CACurrentMediaTime() + desired time offset.

[hideAnimation setBeginTime:CACurrentMediaTime() + 0.09];


回答3:

I'm sure this is too late to do the original poster any good, but it may help others. I've been trying to do something similar, except to make the animation implicit when the hidden property is changed. As Tom says, animating opacity doesn't work in that case, as the change to the layer's hidden property seems to take effect right away (even if I delay the animation with beginTime).

The standard implicit action uses a fade transition (CATransition, type = kCATransitionFade), but this operates on the whole layer and I want to perform another animation at the same time, which is not a compatible operation.

After much experimentation, I finally noticed @Kevin's comment above and --- hello! --- that actually works! So I just wanted to call it out so the solution is more visible to future searchers:

CAKeyframeAnimation* hiddenAnim = [CAKeyframeAnimation animationWithKeyPath:@"hidden"];
hiddenAnim.values = @[@(NO),@(YES)];
hiddenAnim.keyTimes = @[@0.0, @1.0];
hiddenAnim.calculationMode = kCAAnimationDiscrete;
hiddenAnim.duration = duration;

This delays the hiding until the end of the duration. Combine it with other property animations in a group to have their effects seen before the layer disappears. (You can combine this with an opacity animation to have the layer fade out, while performing another animation.)

Thank you, Kevin!



回答4:

    CABasicAnimation *endAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    endAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [endAnimation setFromValue:[NSNumber numberWithFloat:1]];
    [endAnimation setToValue:[NSNumber numberWithFloat:0.0]];
    [endAnimation setBeginTime:AVCoreAnimationBeginTimeAtZero];
    endAnimation.duration            = 5;
    endAnimation.removedOnCompletion = NO;
    [alayer addAnimation:endAnimation forKey:nil];


回答5:

swift 4

    let keyframeAnimation = CAKeyframeAnimation(keyPath: "hidden")
keyframeAnimation.calculationMode = kCAAnimationDiscrete
keyframeAnimation.repeatCount = 1.0
keyframeAnimation.values = [true, false,true,false,true]
keyframeAnimation.keyTimes = [0.0, 0.25,0.5,0.75, 1.0]
keyframeAnimation.duration = 30.0 //duration of the video in my case
keyframeAnimation.beginTime = 0.1
keyframeAnimation.isRemovedOnCompletion = false
keyframeAnimation.fillMode = kCAFillModeBoth

textLayer.add(keyframeAnimation, forKey:  "hidden")