22

アニメーション、CABasicAnimationまたはCAAnimationGroupをチェーンする必要がありますが、その方法がわかりません。唯一の方法は、すべてのアニメーションが同じレイヤーに対して同時に実行されることです。

どうすればいいですか?

たとえば、コンテンツが車の画像に設定されているレイヤー:

1番目:Xポイントを右に移動

2番目:90ªを左に回転します

3番目:Xポイントを移動

4番目:レイヤーをスケーリングします

このアニメーションはすべて秘密裏に実行する必要がありますが、私にはできません:S

ところで:私は英語ではありません。文法に誤りがあった場合は申し訳ありません:D

4

5 に答える 5

35

デビッドが提案するものは問題なく機能しますが、別の方法をお勧めします。

すべてのアニメーションが同じレイヤーにある場合は、アニメーション グループを作成し、各アニメーションに異なる を持たせることができます。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;
于 2012-07-31T20:42:23.043 に答える
23

tl;dr:前の終了後に各アニメーションを手動で追加する必要があります。


シーケンシャル アニメーションを追加する組み込みの方法はありません。各アニメーションの遅延を以前のすべてのアニメーションの合計に設定することもできますが、お勧めしません。

代わりに、すべてのアニメーションを作成し、それらを実行する順序で (配列をキューとして使用して) 可変配列に追加します。次に、すべてのアニメーションに対するアニメーション デリゲートとして自分自身を設定することでanimationDidStop:finished:、アニメーションが終了するたびにコールバックを取得できます。

そのメソッドでは、配列から最初のアニメーション (次のアニメーションを意味する) を削除し、それをレイヤーに追加します。あなたはデリゲートであるため、2 番目のアニメーションが終了すると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];

次に、デリゲート コールバックで、次のアニメーションを再度適用するだけです

- (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];
}

layerToApplyAnimationTo各アニメーションがそのレイヤーを認識できるように、カスタム キーを使用しています(それはsetValue:forKey:とだけで機能しvalueForKey:ます)。

于 2012-07-31T11:09:20.800 に答える
8

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)
于 2016-03-22T23:04:30.823 に答える