如何在iOS应用程序中链接不同的CAAnimation

tor*_*or2 20 core-animation cabasicanimation caanimation

我需要链接动画,CABasicAnimation或CAAnimationGroup,但我不知道如何做,我唯一做的是所有动画同时执行同一层.

我怎么能这样做?

例如,一个内容设置为汽车图像的图层:

1st:将X点向右移动

第二名:向左旋转90ª

第3名:移动X点

第四步:缩放图层

所有这些动画必须以一种安全的方式执行,但我不能这样做:S

顺便说一句:我不是英国人,对不起,如果我在语法上犯了一些错误:D

Dun*_*n C 33

大卫建议什么工作正常,但我会推荐一种不同的方式.

如果所有动画都在同一图层上,则可以创建动画组,并使每个动画具有不同的动画beginTime,其中第一个动画从beginTime0 开始,每个新动画在之前的动画总持续时间之后开始.

如果你的动画是在不同的层,但是,你不能使用动画组(所有的动画的动画组必须在同一层上采取行动.)在这种情况下,您需要提交不同的动画,每一个都具有beginTime这偏离CACurrentMediaTime(),例如:

CGFloat totalDuration = 0;
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath: @"alpha"];
animationOne.beginTime = CACurrentMediaTime(); //Start instantly.
animationOne.duration = animationOneDuration;
...
//add animation to layer

totalDuration += animationOneDuration;

CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath: @"position"];
animationTwo.beginTime = CACurrentMediaTime() + totalDuration; //Start after animation one.
animationTwo.duration = animationTwoDuration;
...
//add animation to layer

totalDuration += animationTwoDuration;


CABasicAnimation *animationThree = [CABasicAnimation animationWithKeyPath: @"position"];
animationThree.beginTime = CACurrentMediaTime() + totalDuration; //Start after animation three.
animationThree.duration = animationThreeDuration;
...
//add animation to layer

totalDuration += animationThreeDuration;
Run Code Online (Sandbox Code Playgroud)

  • 如果这有助于其他人:如果你使用动画组(即不是这里的代码片段而是大卫的第一段),那么animation.beginTim是相对于组....所以你不要将它设置为CACurrentMediaTime (),你只需将它设置为totalDuration.这让我困惑了几分钟...... (6认同)

Dav*_*ist 19

tl; dr:您需要在之前的完成后手动添加每个动画.


没有内置的方法来添加顺序动画.您可以将每个动画的延迟设置为所有先前动画的总和,但我不推荐它.

相反,我会创建所有动画并将它们按照它们应该运行的顺序添加到可变数组(使用数组作为队列).然后通过将自己设置为动画委托给所有动画,您可以animationDidStop:finished:在动画完成时获得回调.

在该方法中,您将从数组中删除第一个动画(表示下一个动画)并将其添加到图层.由于您是委托,因此当第一个动画结束时,您将获得第二个动画,在这种情况下,animationDidStop:finished:回调将再次运行,并且下一个动画将从可变数组中移除并添加到图层中.

一旦动画数组为空,所有动画都将运行.


一些示例代码可以帮助您入门.首先设置所有动画:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
[animation setToValue:(id)[[UIColor redColor] CGColor]];
[animation setDuration:1.5];
[animation setDelegate:self];
[animation setValue:[view layer] forKey:@"layerToApplyAnimationTo"];

// Configure other animations the same way ...

[self setSequenceOfAnimations:[NSMutableArray arrayWithArray: @[ animation, animation1, animation2, animation3, animation4, animation5 ] ]];

// Start the chain of animations by adding the "next" (the first) animation
[self applyNextAnimation];
Run Code Online (Sandbox Code Playgroud)

然后在委托回调中,您只需再次应用下一个动画

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished {
    [self applyNextAnimation];
}

- (void)applyNextAnimation {
     // Finish when there are no more animations to run
    if ([[self sequenceOfAnimations] count] == 0) return;

    // Get the next animation and remove it from the "queue"
    CAPropertyAnimation * nextAnimation = [[self sequenceOfAnimations] objectAtIndex:0];
    [[self sequenceOfAnimations] removeObjectAtIndex:0];

    // Get the layer and apply the animation
    CALayer *layerToAnimate = [nextAnimation valueForKey:@"layerToApplyAnimationTo"];
    [layerToAnimate addAnimation:nextAnimation forKey:nil];
}
Run Code Online (Sandbox Code Playgroud)

我正在使用自定义键,layerToApplyAnimationTo以便每个动画都知道它的图层(它只是通过setValue:forKey:和工作valueForKey:).

  • @RandyJames您可以在添加动画时传递一个键,并使用该键查找正确的数组以从中选择下一个动画。`addAnimation:forKey:` 中的键与 `animationForKeyPath:` 中的键路径不同 (2认同)

小智 7

这是 Swift 中的解决方案:

var animations = [CABasicAnimation]()

var animation1 = CABasicAnimation(keyPath: "key_path_1")
// animation set up here, I've included a few properties as an example
animation1.duration = 1.0
animation1.fromValue = 1
animation1.toValue = 0
animations.append(animation1)
    
var animation2 = CABasicAnimation(keyPath: "key_path_2")
animation2.duration = 1.0
animation2.fromValue = 1
animation2.toValue = 0
// setting beginTime is the key to chaining these
animation2.beginTime = 1.0
animations.append(animation2)
    
let group = CAAnimationGroup()
group.duration = 2.0
group.repeatCount = FLT_MAX
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
group.animations = animations
    
yourLayer.addAnimation(group, forKey: nil)
Run Code Online (Sandbox Code Playgroud)